From: Sehong Na Date: Sat, 31 May 2014 04:20:11 +0000 (+0900) Subject: Initialize Tizen 2.3 X-Git-Tag: 2.3a_release X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=764ea635f2e980157258d6c3107a4480a6ae12d0;p=framework%2Fweb%2Fwrt-installer.git Initialize Tizen 2.3 --- 764ea635f2e980157258d6c3107a4480a6ae12d0 diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100755 index 0000000..350168c --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,139 @@ +# Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @file CMakeLists.txt +# @author Bartlomiej Grzelewski (b.grzelewski@samsung.com) +# @brief +# + +############################# Check minimum CMake version ##################### + +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +PROJECT("wrt-installer") + +############################# cmake packages ################################## + +INCLUDE(FindPkgConfig) + +############################# build type ###################################### + +IF(NOT CMAKE_BUILD_TYPE) + SET(CMAKE_BUILD_TYPE "Release") +ENDIF(NOT CMAKE_BUILD_TYPE) + +############################# compilation defines ############################# + +OPTION(DPL_LOG "DPL logs status" ON) +OPTION(WITH_TESTS "Build tests" OFF) +OPTION(MULTIPROCESS_SERVICE_SUPPORT "Process per service" OFF) +OPTION(MULTIPROCESS_SERVICE_SUPPORT_INLINE "Process per service - inline mode support" OFF) +OPTION(SCHEMA_VALIDATION_SUPPORT "Support for XML schema validation" OFF) +OPTION(NFC_APP_CONTROL_EXCEPTION "Enable exception handling for NFC app-control" ON) + +SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/build") +INCLUDE(Options) + +############################# compiler flags ################################## + +SET(CMAKE_C_FLAGS_PROFILING "-O2") +SET(CMAKE_CXX_FLAGS_PROFILING "-O2 -std=c++0x") +SET(CMAKE_C_FLAGS_DEBUG "-O0 -g") +SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -std=c++0x -g") +SET(CMAKE_C_FLAGS_RELEASE "-O2 -g") +SET(CMAKE_CXX_FLAGS_RELEASE "-O2 -std=c++0x -g -fvisibility-inlines-hidden") +SET(CMAKE_CXX_FLAGS_CCOV "-O0 -std=c++0x -g --coverage") + +IF(DPL_LOG AND NOT CMAKE_BUILD_TYPE MATCHES "profiling") + MESSAGE(STATUS "Logging enabled for DPL") + ADD_DEFINITIONS("-DDPL_LOGS_ENABLED") +ELSE(DPL_LOG AND NOT CMAKE_BUILD_TYPE MATCHES "profiling") + MESSAGE(STATUS "Logging disabled for DPL") +ENDIF(DPL_LOG AND NOT CMAKE_BUILD_TYPE MATCHES "profiling") +MESSAGE(STATUS "WITH_TESTS: " ${WITH_TESTS}) +IF(MULTIPROCESS_SERVICE_SUPPORT) + ADD_DEFINITIONS("-DMULTIPROCESS_SERVICE_SUPPORT") + IF (MULTIPROCESS_SERVICE_SUPPORT_INLINE) + ADD_DEFINITIONS("-DMULTIPROCESS_SERVICE_SUPPORT_INLINE") + ENDIF(MULTIPROCESS_SERVICE_SUPPORT_INLINE) +ENDIF(MULTIPROCESS_SERVICE_SUPPORT) +IF(SCHEMA_VALIDATION_SUPPORT) + MESSAGE(STATUS "XML Schema validation of installed app enabled") + ADD_DEFINITIONS("-DSCHEMA_VALIDATION_ENABLED") +ENDIF(SCHEMA_VALIDATION_SUPPORT) +IF(NFC_APP_CONTROL_EXCEPTION) + MESSAGE(STATUS "Exception handling for NFC app-control is enabled") + ADD_DEFINITIONS("-DNFC_EXCEPTION_HANDLING_FOR_TIZEN_2_2_ONLY") +ENDIF(NFC_APP_CONTROL_EXCEPTION) + +IF(DEVICE_PROFILE STREQUAL "wearable") + MESSAGE(STATUS "Device Profile: wearable") + ADD_DEFINITIONS("-DDEVICE_PROFILE_WEARABLE") +ELSE(DEVICE_PROFILE STREQUAL "wearable") + MESSAGE(STATUS "Device Profile: mobile") + ADD_DEFINITIONS("-DDEVICE_PROFILE_MOBILE") + ADD_DEFINITIONS("-DWRT_SMACK_ENABLED") # enable smack + + OPTION(CSP_SUPPORT "Support for csp policy" ON) + OPTION(ALLOW_NAVIGATION_SUPPORT "Support for allow-navigation" ON) + + IF(CSP_SUPPORT) + ADD_DEFINITIONS("-DCSP_ENABLED") + ENDIF(CSP_SUPPORT) + IF(ALLOW_NAVIGATION_SUPPORT) + ADD_DEFINITIONS("-DALLOW_NAVIGATION_ENABLED") + ENDIF(ALLOW_NAVIGATION_SUPPORT) +ENDIF(DEVICE_PROFILE STREQUAL "wearable") + +# If supported for the target machine, emit position-independent code,suitable +# for dynamic linking and avoiding any limit on the size of the global offset +# table. This option makes a difference on the m68k, PowerPC and SPARC. +# (BJ: our ARM too?) +ADD_DEFINITIONS("-fPIC") + +# Set the default ELF image symbol visibility to hidden - all symbols will be +# marked with this unless overridden within the code. +#ADD_DEFINITIONS("-fvisibility=hidden") + +# Set compiler warning flags +#ADD_DEFINITIONS("-Werror") # Make all warnings into errors. +ADD_DEFINITIONS("-Wall") # Generate all warnings +ADD_DEFINITIONS("-Wextra") # Generate even more extra warnings +ADD_DEFINITIONS("-Wno-variadic-macros") # Inhibit variadic macros warnings (needed for ORM) +ADD_DEFINITIONS("-Wno-deprecated") # No warnings about deprecated features +ADD_DEFINITIONS("-std=c++0x") # accept C++11x standard +ADD_DEFINITIONS("-DWRT_INSTALLER_LOG") # enable installer log +ADD_DEFINITIONS("-DDBOX_ENABLED") # enable dynamic box features +ADD_DEFINITIONS("-DIME_ENABLED") # enable Ime features +ADD_DEFINITIONS("-DSERVICE_ENABLED") # enable Service features + +############################# Targets names ################################### + +SET(TARGET_INSTALLER_STATIC "wrt-installer_static") +SET(TARGET_INSTALLER "wrt-installer") +SET(TARGET_BACKEND_LIB "wgt") + +############################# subdirectories ################################## +ADD_SUBDIRECTORY(src) +ADD_SUBDIRECTORY(configuration) + +IF(WITH_TESTS) + ADD_SUBDIRECTORY(tests) +ENDIF(WITH_TESTS) + +########################## smack rule install ################################# +INSTALL(FILES ${CMAKE_SOURCE_DIR}/wrt-installer.rule + DESTINATION /etc/smack/accesses2.d/ +) + + diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..247c97d --- /dev/null +++ b/LICENSE @@ -0,0 +1,203 @@ +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/build/Options.cmake b/build/Options.cmake new file mode 100644 index 0000000..05087e0 --- /dev/null +++ b/build/Options.cmake @@ -0,0 +1,42 @@ +# Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# @file Options.cmake +# @author Tae-Jeong Lee (taejeong.lee@samsung.com) +# + +# Macro declaration +# - WRT_OPTION() : Wrapper omitting description argument from OPTION() command. +MACRO(WRT_OPTION feature_name on_off) + OPTION(${feature_name} "" ${on_off}) +ENDMACRO(WRT_OPTION) + +# Use Feature +# Use a particular optional platform service or third-party library +# +# Description : +# +# Author : () - +# WRT_OPTION(_USE_ ON/OFF) + + +# Enable Feature +# Turn on a specific feature of WRT +# +# Description : +# +# Author : () - +# WRT_OPTION(_ENABLE_ ON/OFF) + diff --git a/configuration/CMakeLists.txt b/configuration/CMakeLists.txt new file mode 100644 index 0000000..380f512 --- /dev/null +++ b/configuration/CMakeLists.txt @@ -0,0 +1,2 @@ +FILE(GLOB XSD_FILES "${CMAKE_CURRENT_SOURCE_DIR}/*.xsd") +INSTALL(FILES ${XSD_FILES} DESTINATION /usr/etc/wrt-installer/) diff --git a/configuration/access.xsd b/configuration/access.xsd new file mode 100644 index 0000000..f2404e4 --- /dev/null +++ b/configuration/access.xsd @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + diff --git a/configuration/common.xsd b/configuration/common.xsd new file mode 100644 index 0000000..2b9a0d2 --- /dev/null +++ b/configuration/common.xsd @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/configuration/config.xml b/configuration/config.xml new file mode 100755 index 0000000..492e3df --- /dev/null +++ b/configuration/config.xml @@ -0,0 +1,78 @@ + + + hello + hello + + + + + + + + + + + + + + + + + + + + 6135122a-a428-40d2-8feb-a75f462c202c + + en-us + ko-kr + + + + + + + WebService + + WebService + + + + "img-src http://test.com 'unsafe-inline'; script-src 'unsafe-inline';" + + + + + + + + + + + + + + + + + diff --git a/configuration/feature-wrt.properties b/configuration/feature-wrt.properties new file mode 100644 index 0000000..5b7fb11 --- /dev/null +++ b/configuration/feature-wrt.properties @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/configuration/local.xsd b/configuration/local.xsd new file mode 100644 index 0000000..4aecb7d --- /dev/null +++ b/configuration/local.xsd @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/configuration/packaging-configuration.xsd b/configuration/packaging-configuration.xsd new file mode 100755 index 0000000..0990be2 --- /dev/null +++ b/configuration/packaging-configuration.xsd @@ -0,0 +1,230 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/configuration/privilege-wrt.properties b/configuration/privilege-wrt.properties new file mode 100644 index 0000000..dc36b93 --- /dev/null +++ b/configuration/privilege-wrt.properties @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/configuration/signature_schema.xsd b/configuration/signature_schema.xsd new file mode 100644 index 0000000..1ca3bd3 --- /dev/null +++ b/configuration/signature_schema.xsd @@ -0,0 +1,310 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/configuration/updates.xsd b/configuration/updates.xsd new file mode 100644 index 0000000..6e6d88a --- /dev/null +++ b/configuration/updates.xsd @@ -0,0 +1,15 @@ + + + + + + + + + + + + diff --git a/configuration/validate-config.xml.sh b/configuration/validate-config.xml.sh new file mode 100755 index 0000000..a242910 --- /dev/null +++ b/configuration/validate-config.xml.sh @@ -0,0 +1,2 @@ +#!/bin/sh +xmllint --schema widgets.xsd config.xml diff --git a/configuration/widgets.tizen.xsd b/configuration/widgets.tizen.xsd new file mode 100755 index 0000000..e849e30 --- /dev/null +++ b/configuration/widgets.tizen.xsd @@ -0,0 +1,341 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/configuration/widgets.xsd b/configuration/widgets.xsd new file mode 100644 index 0000000..8de2f3d --- /dev/null +++ b/configuration/widgets.xsd @@ -0,0 +1,20 @@ + + + + + + diff --git a/configuration/xml.xsd b/configuration/xml.xsd new file mode 100644 index 0000000..715330a --- /dev/null +++ b/configuration/xml.xsd @@ -0,0 +1,4 @@ + + + + diff --git a/packaging/wrt-installer.spec b/packaging/wrt-installer.spec new file mode 100755 index 0000000..11630ec --- /dev/null +++ b/packaging/wrt-installer.spec @@ -0,0 +1,135 @@ +#git:framework/web/wrt-installer +Name: wrt-installer +Summary: Installer for tizen Webruntime +Version: 0.1.175_w11 +Release: 1 +Group: Development/Libraries +License: Apache License, Version 2.0 +URL: N/A +Source0: %{name}-%{version}.tar.gz +BuildRequires: cmake +BuildRequires: edje-tools +BuildRequires: pkgconfig(appsvc) +BuildRequires: pkgconfig(libxml-2.0) +BuildRequires: pkgconfig(openssl) +BuildRequires: pkgconfig(dpl-efl) +BuildRequires: pkgconfig(cert-svc-vcore) +BuildRequires: pkgconfig(dpl-event-efl) +BuildRequires: pkgconfig(dpl-utils-efl) +BuildRequires: pkgconfig(dpl-wrt-dao-ro) +BuildRequires: pkgconfig(dpl-wrt-dao-rw) +BuildRequires: pkgconfig(wrt-commons-i18n-dao-ro) +BuildRequires: pkgconfig(wrt-commons-widget-interface-dao) +BuildRequires: pkgconfig(security-install) +BuildRequires: pkgconfig(ecore-x) +BuildRequires: pkgconfig(xmlsec1) +BuildRequires: pkgconfig(libidn) +BuildRequires: pkgconfig(libiri) +BuildRequires: pkgconfig(libpcrecpp) +BuildRequires: pkgconfig(pkgmgr-installer) +BuildRequires: pkgconfig(pkgmgr-parser) +BuildRequires: pkgconfig(pkgmgr-types) +BuildRequires: pkgconfig(pkgmgr-info) +BuildRequires: pkgconfig(pkgmgr) +BuildRequires: pkgconfig(dlog) +BuildRequires: pkgconfig(cert-svc) +BuildRequires: pkgconfig(utilX) +BuildRequires: pkgconfig(wrt-plugins-types) +BuildRequires: pkgconfig(tapi) +BuildRequires: pkgconfig(shortcut) +BuildRequires: pkgconfig(capi-appfw-app-manager) +BuildRequires: pkgconfig(capi-system-power) +BuildRequires: pkgconfig(app2sd) +BuildRequires: pkgconfig(web-provider) +BuildRequires: pkgconfig(libprivilege-control) +BuildRequires: pkgconfig(libsmack) +BuildRequires: libss-client-devel +BuildRequires: boost-devel +Requires: libss-client +Requires: xmlsec1 +Requires: wrt-plugins-tizen + +%description +Description: Wrt Installer for Tizen apps and Wac apps + +%prep +%setup -q + +%define with_tests 0 +%if "%{WITH_TESTS}" == "ON" || "%{WITH_TESTS}" == "Y" || "%{WITH_TESTS}" == "YES" || "%{WITH_TESTS}" == "TRUE" || "%{WITH_TESTS}" == "1" + %define with_tests 1 +%endif + +%build +%if 0%{?sec_build_binary_debug_enable} +export CFLAGS="$CFLAGS -DTIZEN_DEBUG_ENABLE" +export CXXFLAGS="$CXXFLAGS -DTIZEN_DEBUG_ENABLE" +export FFLAGS="$FFLAGS -DTIZEN_DEBUG_ENABLE" +%endif + +%if "%{_repository}" == "wearable" + %define device_profile wearable +%else + %define device_profile mobile +%endif + +export LDFLAGS+="-Wl,--rpath=/usr/lib -Wl,--hash-style=both -Wl,--as-needed" +LDFLAGS="$LDFLAGS" + +%if "%{_repository}" == "wearable" + ln -sf src_wearable src +%else + ln -sf src_mobile src +%endif + +cmake . -DCMAKE_INSTALL_PREFIX=/usr \ + -DDPL_LOG=ON \ + -DLB_SUPPORT=ON \ + -DCMAKE_BUILD_TYPE=%{?build_type:%build_type} \ + -DDEVICE_PROFILE=%{?device_profile:%device_profile} \ + %{?WITH_TESTS:-DWITH_TESTS=%WITH_TESTS} +make %{?jobs:-j%jobs} + +%install +rm -rf %{buildroot} +mkdir -p %{buildroot}/usr/share/license +cp LICENSE %{buildroot}/usr/share/license/%{name} +%make_install + +%clean +rm -rf %{buildroot} + +%post +/sbin/ldconfig + +#symlink for package manager +%define pkg_manager_backend_path "/usr/etc/package-manager/backend" +ln -sf /usr/bin/wrt-installer %{pkg_manager_backend_path}/wgt +ln -sf %{pkg_manager_backend_path}/wgt %{pkg_manager_backend_path}/Wgt +ln -sf %{pkg_manager_backend_path}/wgt %{pkg_manager_backend_path}/wGt +ln -sf %{pkg_manager_backend_path}/wgt %{pkg_manager_backend_path}/wgT +ln -sf %{pkg_manager_backend_path}/wgt %{pkg_manager_backend_path}/WGt +ln -sf %{pkg_manager_backend_path}/wgt %{pkg_manager_backend_path}/wGT +ln -sf %{pkg_manager_backend_path}/wgt %{pkg_manager_backend_path}/WgT +ln -sf %{pkg_manager_backend_path}/wgt %{pkg_manager_backend_path}/WGT + +#for booting recovery +mkdir -p /opt/share/widget/temp_info + +# for downloadable Application icons path +mkdir -p /opt/share/icons/default/small + +%postun -p /sbin/ldconfig + +%files +%manifest wrt-installer.manifest +%attr(755,root,root) %{_bindir}/wrt-installer +/usr/etc/package-manager/backendlib/libwgt.so +%attr(644,root,root) /usr/etc/wrt-installer/*.xsd +%{_datadir}/license/%{name} +%if %{with_tests} + %attr(755,root,root) %{_bindir}/wrt-installer-tests-* + /opt/share/widget/tests/installer/widgets/* + /opt/share/widget/tests/installer/configs/* +%endif +%{_sysconfdir}/smack/accesses2.d/wrt-installer.rule diff --git a/src_mobile/CMakeLists.txt b/src_mobile/CMakeLists.txt new file mode 100644 index 0000000..bd52dcf --- /dev/null +++ b/src_mobile/CMakeLists.txt @@ -0,0 +1,185 @@ +# Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# @file CMakeLists.txt +# @author Lukasz Wrzosek (l.wrzosek@samsung.com) +# @version 1.0 +# + +SET(TARGET_INSTALLER "wrt-installer") + +OPTION(LB_SUPPORT "lb support" OFF) + +SET(INSTALLER_SRC_DIR + ${PROJECT_SOURCE_DIR}/src_mobile + ) + +SET(INSTALLER_CONFIG_PARSER + ${INSTALLER_SRC_DIR}/configuration_parser + ) + +SET(INSTALLER_JOBS + ${INSTALLER_SRC_DIR}/jobs + ) + +SET(INSTALLER_INCLUDES + ${INSTALLER_SRC_DIR} + ${INSTALLER_SRC_DIR}/logic + ${INSTALLER_SRC_DIR}/jobs + ${INSTALLER_SRC_DIR}/jobs/plugin_install + ${INSTALLER_SRC_DIR}/jobs/widget_install + ${INSTALLER_SRC_DIR}/jobs/widget_uninstall + ${INSTALLER_SRC_DIR}/misc + ${INSTALLER_SRC_DIR}/configuration_parser + ${INSTALLER_SRC_DIR}/wrt-installer + ${INSTALLER_SRC_DIR}/commons + ${INSTALLER_SRC_DIR}/pkg-manager +) + +SET(INSTALLER_SOURCES + ${INSTALLER_CONFIG_PARSER}/widget_parser.cpp + ${INSTALLER_CONFIG_PARSER}/parser_runner.cpp + ${INSTALLER_CONFIG_PARSER}/ignoring_parser.cpp + ${INSTALLER_CONFIG_PARSER}/deny_all_parser.cpp + ${INSTALLER_CONFIG_PARSER}/libiriwrapper.cpp + ${INSTALLER_JOBS}/job.cpp + ${INSTALLER_JOBS}/plugin_install/job_plugin_install.cpp + ${INSTALLER_JOBS}/plugin_install/plugin_install_task.cpp + ${INSTALLER_JOBS}/plugin_install/plugin_objects.cpp + ${INSTALLER_JOBS}/plugin_install/plugin_metafile_reader.cpp + ${INSTALLER_JOBS}/widget_install/job_widget_install.cpp + ${INSTALLER_JOBS}/widget_install/manifest.cpp + ${INSTALLER_JOBS}/widget_install/task_commons.cpp + ${INSTALLER_JOBS}/widget_install/task_process_config.cpp + ${INSTALLER_JOBS}/widget_install/task_database.cpp + ${INSTALLER_JOBS}/widget_install/task_configuration.cpp + ${INSTALLER_JOBS}/widget_install/ace_registration.cpp + ${INSTALLER_JOBS}/widget_install/task_file_manipulation.cpp + ${INSTALLER_JOBS}/widget_install/task_user_data_manipulation.cpp + ${INSTALLER_JOBS}/widget_install/task_smack.cpp + ${INSTALLER_JOBS}/widget_install/task_ace_check.cpp + ${INSTALLER_JOBS}/widget_install/task_manifest_file.cpp + ${INSTALLER_JOBS}/widget_install/task_certify.cpp + ${INSTALLER_JOBS}/widget_install/task_certify_level.cpp + ${INSTALLER_JOBS}/widget_install/task_prepare_files.cpp + ${INSTALLER_JOBS}/widget_install/task_recovery.cpp + ${INSTALLER_JOBS}/widget_install/task_install_ospsvc.cpp + ${INSTALLER_JOBS}/widget_install/task_update_files.cpp + ${INSTALLER_JOBS}/widget_install/task_remove_backup.cpp + ${INSTALLER_JOBS}/widget_install/task_encrypt_resource.cpp + ${INSTALLER_JOBS}/widget_install/task_prepare_reinstall.cpp + ${INSTALLER_JOBS}/widget_install/task_pkg_info_update.cpp + ${INSTALLER_JOBS}/widget_install/widget_security.cpp + ${INSTALLER_JOBS}/widget_install/widget_update_info.cpp + ${INSTALLER_JOBS}/widget_install/directory_api.cpp + ${INSTALLER_JOBS}/widget_install/widget_unzip.cpp + ${INSTALLER_JOBS}/widget_uninstall/job_widget_uninstall.cpp + ${INSTALLER_JOBS}/widget_uninstall/task_check.cpp + ${INSTALLER_JOBS}/widget_uninstall/task_remove_files.cpp + ${INSTALLER_JOBS}/widget_uninstall/task_remove_custom_handlers.cpp + ${INSTALLER_JOBS}/widget_uninstall/task_db_update.cpp + ${INSTALLER_JOBS}/widget_uninstall/task_smack.cpp + ${INSTALLER_JOBS}/widget_uninstall/task_uninstall_ospsvc.cpp + ${INSTALLER_JOBS}/widget_uninstall/task_delete_pkginfo.cpp + ${INSTALLER_SRC_DIR}/logic/installer_logic.cpp + ${INSTALLER_SRC_DIR}/logic/installer_controller.cpp + ${INSTALLER_SRC_DIR}/misc/wac_widget_id.cpp + ${INSTALLER_SRC_DIR}/misc/feature_logic.cpp + ${INSTALLER_SRC_DIR}/misc/libxml_utils.cpp + ${INSTALLER_SRC_DIR}/misc/widget_location.cpp + ${INSTALLER_SRC_DIR}/misc/widget_install_to_external.cpp + ${INSTALLER_SRC_DIR}/misc/plugin_path.cpp + ${INSTALLER_SRC_DIR}/pkg-manager/pkgmgr_signal.cpp + ) + +IF(LB_SUPPORT) + SET(INSTALLER_SOURCES + ${INSTALLER_SOURCES} + ) + MESSAGE(STATUS "adding definition -DLB_SUPPORT") + ADD_DEFINITIONS("-DLB_SUPPORT") +ENDIF(LB_SUPPORT) + +MESSAGE(STATUS "add -DSEP_INSTALLER") +ADD_DEFINITIONS("-DSEP_INSTALLER") + + +PKG_CHECK_MODULES(INSTALLER_STATIC_DEP + dpl-efl + dpl-event-efl + dpl-utils-efl + dpl-wrt-dao-ro + dpl-wrt-dao-rw + wrt-commons-custom-handler-dao-rw + wrt-commons-security-origin-dao + wrt-commons-widget-interface-dao + wrt-plugins-types + pkgmgr-installer + pkgmgr-parser + pkgmgr-info + web-provider + libsmack + REQUIRED +) + +PKG_CHECK_MODULES(SYS_INSTALLER_STATIC_DEP + appsvc + libxml-2.0 + openssl + cert-svc-vcore + security-install + ecore-x + xmlsec1 + libidn + libiri + libpcrecpp + ail + elementary + tapi + shortcut + capi-appfw-app-manager + app2sd + libprivilege-control + REQUIRED +) + +INCLUDE_DIRECTORIES( SYSTEM ${SYS_INSTALLER_STATIC_DEP_INCLUDE_DIRS}) + +INCLUDE_DIRECTORIES( + ${INSTALLER_DEP_INCLUDES} + ${INSTALLER_INCLUDES} + ${INSTALLER_STATIC_DEP_INCLUDE_DIRS} + ${OSP_APPFW_INCLUDES} + ) + +ADD_LIBRARY(${TARGET_INSTALLER_STATIC} STATIC + ${INSTALLER_SOURCES} + ) + +ADD_DEFINITIONS(${INSTALLER_STATIC_DEP_CFLAGS}) +ADD_DEFINITIONS(${INSTALLER_STATIC_DEP_CFLAGS_OTHERS}) +ADD_DEFINITIONS(${SYS_INSTALLER_STATIC_DEP_CFLAGS}) +ADD_DEFINITIONS(${SYS_INSTALLER_STATIC_DEP_CFLAGS_OTHERS}) + +TARGET_LINK_LIBRARIES(${TARGET_INSTALLER_STATIC} + ${INSTALLER_STATIC_DEP_LIBRARIES} "-ldl" + ${SYS_INSTALLER_STATIC_DEP_LIBRARIES} "-ldl" + ) + +#for encryption +TARGET_LINK_LIBRARIES(${TARGET_INSTALLER_STATIC} "-lss-client" ) + +ADD_SUBDIRECTORY(pkg-manager) +ADD_SUBDIRECTORY(wrt-installer) diff --git a/src_mobile/DESCRIPTION b/src_mobile/DESCRIPTION new file mode 100644 index 0000000..0e8c571 --- /dev/null +++ b/src_mobile/DESCRIPTION @@ -0,0 +1,2 @@ +!!!options!!! stop +Widget (un)installer, plugin (un)installer diff --git a/src_mobile/commons/installer_log.h b/src_mobile/commons/installer_log.h new file mode 100644 index 0000000..6ba4137 --- /dev/null +++ b/src_mobile/commons/installer_log.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file installer_log.h + * @author Sungsu Kim(sung-su.kim@samsung.com) + * @version 0.1 + * @brief + */ + +#ifndef INSTALLER_LOG_H +#define INSTALLER_LOG_H + +#include + +#ifdef WRT_INSTALLER_LOG + +#undef COLOR_WARNING +#define COLOR_WARNING "\e[0m" +#undef COLOR_TAG +#define COLOR_TAG "\e[0m" + +#endif + +#endif // INSTALLER_LOG_H + diff --git a/src_mobile/commons/wrt_common_types.h b/src_mobile/commons/wrt_common_types.h new file mode 100644 index 0000000..d9ea0f0 --- /dev/null +++ b/src_mobile/commons/wrt_common_types.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * plugin_common_types.h + * + * Author: Soyoung Kim(sy037.kim@samsung.com) + */ + +#ifndef PLUGIN_COMMON_TYPES_H +#define PLUGIN_COMMON_TYPES_H + +#include +#include + +/** + * Widget version is optional + */ +typedef DPL::Optional OptionalWidgetVersion; + +/* Define db type */ +typedef WrtDB::DbWidgetFeature WidgetFeature; +typedef WrtDB::DbWidgetFeatureSet WidgetFeatureSet; + +typedef WrtDB::DbWidgetSize WidgetSize; + +typedef WrtDB::DbPluginHandle PluginHandle; + +enum InstallLocationType +{ + INSTALL_LOCATION_TYPE_UNKNOWN = 0, + INSTALL_LOCATION_TYPE_INTERNAL_ONLY, + INSTALL_LOCATION_TYPE_AUTO, + INSTALL_LOCATION_TYPE_PREFER_EXTERNAL, +}; + +#endif /* PLUGIN_COMMON_TYPES_H */ diff --git a/src_mobile/commons/wrt_error.h b/src_mobile/commons/wrt_error.h new file mode 100644 index 0000000..ae4f2de --- /dev/null +++ b/src_mobile/commons/wrt_error.h @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * This file contains the declaration of the error codes of Widget. + * + * @file wrt_error.h + * @author MaQuan (jason.ma@samsung.com) + * @version 0.7 + * @brief This file contains the declaration of the error codes of Widget. + */ + +#ifndef _WRT_ERROR_H_ +#define _WRT_ERROR_H_ + +#ifndef WRT_ERROR_MASKL8 +#define WRT_ERROR_MASKL8 0xFF +#endif + +#ifndef WRT_SET_IDENT +#define WRT_SET_IDENT(X) (X & WRT_ERROR_MASKL8) +#endif + +#ifndef WRT_ERROR_SET +#define WRT_ERROR_SET(X) ((X & WRT_ERROR_MASKL8) << 8) +#endif + +#define WRT_MID_ERRCODE 0x10000 + WRT_SET_IDENT(5) + +/*typedef */ enum +{ + WRT_GENERAL_ERRCODE = WRT_MID_ERRCODE + WRT_SET_IDENT(0), + WRT_CONFIG_ERRCODE = WRT_MID_ERRCODE + WRT_SET_IDENT(1), + WRT_DOMAIN_ERRCODE = WRT_MID_ERRCODE + WRT_SET_IDENT(2), + WRT_JS_EXT_ERRCODE = WRT_MID_ERRCODE + WRT_SET_IDENT(3), + WRT_WM_ERRCODE = WRT_MID_ERRCODE + WRT_SET_IDENT(4), + WRT_PLUGIN_ERRCODE = WRT_MID_ERRCODE + WRT_SET_IDENT(5), + //_ACE support + WRT_SAI_ERRCODE = WRT_MID_ERRCODE + WRT_SET_IDENT(6) +}; + +/** + * WRT error code description + * + * @ WRT_SUCCESS + * There is no error with WRT operations. + * + * @ WRT_ERR_UNKNOW + * An unknow error happened to WRT. + * + * @ WRT_ERR_INVALID_ARG + * Invalid arguments are passed into WRT functions. + * + * @ WRT_ERR_OUT_MEMORY + * No memory space available for WRT. + * + * @ WRT_ERR_NO_DISK_SPACE + * There is no disk space for widget applications. + * + * + * + * + */ +enum WrtError +{ + /* General errors */ + WRT_SUCCESS = WRT_GENERAL_ERRCODE + WRT_ERROR_SET(0x01), + WRT_ERR_UNKNOWN = WRT_GENERAL_ERRCODE + WRT_ERROR_SET(0x02), + WRT_ERR_INVALID_ARG = WRT_GENERAL_ERRCODE + WRT_ERROR_SET(0x03), + WRT_ERR_OUT_OF_MEMORY = WRT_GENERAL_ERRCODE + WRT_ERROR_SET(0x04), + WRT_ERR_NO_DISK_SPACE = WRT_GENERAL_ERRCODE + WRT_ERROR_SET(0x05), + + /* Configuration */ + WRT_CONF_ERR_GCONF_FAILURE = WRT_CONFIG_ERRCODE + WRT_ERROR_SET(0x01), + WRT_CONF_ERR_OBJ_MISSING = WRT_CONFIG_ERRCODE + WRT_ERROR_SET(0x02), + WRT_CONF_ERR_OBJ_EXIST = WRT_CONFIG_ERRCODE + WRT_ERROR_SET(0x03), + WRT_CONF_ERR_START_FILE_MISSING = WRT_CONFIG_ERRCODE + WRT_ERROR_SET(0x04), + WRT_CONF_ERR_EMDB_FAILURE = WRT_CONFIG_ERRCODE + WRT_ERROR_SET(0x05), + WRT_CONF_ERR_EMDB_NO_RECORD = WRT_CONFIG_ERRCODE + WRT_ERROR_SET(0x06), + + /* Domain */ + WRT_DOMAIN_ERR_CREATE_JS_RT = WRT_DOMAIN_ERRCODE + WRT_ERROR_SET(0x01), + WRT_DOMAIN_ERR_MSG_QUEUE = WRT_DOMAIN_ERRCODE + WRT_ERROR_SET(0x02), + + /* Widget manager*/ + WRT_WM_ERR_NOT_INSTALLED = WRT_WM_ERRCODE + WRT_ERROR_SET(0x01), + WRT_WM_ERR_HIGH_VER_INSTALLED = WRT_WM_ERRCODE + WRT_ERROR_SET(0x02), + WRT_WM_ERR_LOW_VER_INSTALLED = WRT_WM_ERRCODE + WRT_ERROR_SET(0x03), + WRT_WM_ERR_INVALID_ARCHIVE = WRT_WM_ERRCODE + WRT_ERROR_SET(0x04), + WRT_WM_ERR_INVALID_CERTIFICATION = WRT_WM_ERRCODE + WRT_ERROR_SET(0x05), + WRT_WM_ERR_NULL_CERTIFICATION = WRT_WM_ERRCODE + WRT_ERROR_SET(0x06), + WRT_WM_ERR_INSTALLATION_CANCEL = WRT_WM_ERRCODE + WRT_ERROR_SET(0x07), + WRT_WM_ERR_ALREADY_INSTALLED = WRT_WM_ERRCODE + WRT_ERROR_SET(0x08), + WRT_WM_ERR_INSTALL_FAILED = WRT_WM_ERRCODE + WRT_ERROR_SET(0x09), + WRT_WM_ERR_DELETE_BY_SERVER = WRT_WM_ERRCODE + WRT_ERROR_SET(0x0a), + WRT_WM_ERR_DEINSTALLATION_CANCEL = WRT_WM_ERRCODE + WRT_ERROR_SET(0x0b), + WRT_WM_ERR_INCORRECT_UPDATE_INFO = WRT_WM_ERRCODE + WRT_ERROR_SET(0x0c), + WRT_WM_ERR_UNREG_FAILED = WRT_WM_ERRCODE + WRT_ERROR_SET(0x0d), + WRT_WM_ERR_REMOVE_FILES_FAILED = WRT_WM_ERRCODE + WRT_ERROR_SET(0x0e), + WRT_WM_ERR_ALREADY_LATEST = WRT_WM_ERRCODE + WRT_ERROR_SET(0x0f), + WRT_WM_ERR_UPDATE_CANCEL = WRT_WM_ERRCODE + WRT_ERROR_SET(0x10), + WRT_WM_ERR_INVALID_APP_ID = WRT_WM_ERRCODE + WRT_ERROR_SET(0x11), + + /* Access Control Manager */ + WRT_SAI_ERR_INIT_ACE_FAILED = WRT_SAI_ERRCODE + WRT_ERROR_SET(0x01) +}; + +namespace CommonError { +enum Type +{ + WrtSuccess, ///< Success + + HandleNotFound, ///< Widget handle was not found + AlreadyRunning, ///< Widget is already running + AlreadyStopped, ///< Widget is already stopped + InvalidLanguage, ///< Widget is invalid in current locales + StillAuthorizing, ///< Widget is still autorizing and has not yet + // finished it + EarlyKilled, ///< Widget was early killed during launch + AccessDenied, ///< Access denied from ACE + CertificateRevoked, ///< Some certificate was revoked. + /// Widget is not allowed to run. + + Unknown ///< Temporary error. Try to not use this. +}; +} +#endif /* _WRT_ERROR_H_ */ + diff --git a/src_mobile/commons/wrt_install_mode.h b/src_mobile/commons/wrt_install_mode.h new file mode 100644 index 0000000..714d3c3 --- /dev/null +++ b/src_mobile/commons/wrt_install_mode.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file wrt_install_mode.h + * @author Jihoon Chung (jihoon.chung@samgsung.com) + * @version + * @brief Definition file of widget install mode class + */ + +#ifndef WRT_INSTALL_MODE_H +#define WRT_INSTALL_MODE_H + +class InstallMode +{ + public: + enum class Command + { + INSTALL, + REINSTALL + }; + enum class Location + { + INTERNAL, + EXTERNAL + }; + enum class RootPath + { + RW, + RO + }; + enum class ExtensionType + { + WGT, + DIR + }; + enum class InstallTime + { + NORMAL, + CSC, + PRELOAD, + }; + + InstallMode(Command cmd = Command::INSTALL, + Location lo = Location::INTERNAL, + RootPath root = RootPath::RW, + ExtensionType extensionType = ExtensionType::WGT, + InstallTime time = InstallTime::NORMAL) : + command(cmd), + location(lo), + rootPath(root), + extension(extensionType), + installTime(time), + removable(true) + {}; + + Command command; + Location location; + RootPath rootPath; + ExtensionType extension; + InstallTime installTime; + bool removable; +}; + +#endif // WRT_INSTALL_MODE_H + diff --git a/src_mobile/configuration_parser/deny_all_parser.cpp b/src_mobile/configuration_parser/deny_all_parser.cpp new file mode 100644 index 0000000..e807d5e --- /dev/null +++ b/src_mobile/configuration_parser/deny_all_parser.cpp @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "deny_all_parser.h" +#include + +DenyAllParser::DenyAllParser() : ElementParser() +{} + +ElementParserPtr DenyAllParser::Create() +{ + ThrowMsg(Exception::ParseError, "There must not be any subelement"); +} + +ElementParser::ActionFunc DenyAllParser::GetElementParser(const DPL::String& /*ns*/, + const DPL::String& /*name*/) +{ + ThrowMsg(Exception::ParseError, "There must not be any subelement"); +} + +void DenyAllParser::Accept(const Element& /*element*/) +{ + ThrowMsg(Exception::ParseError, "There must not be any element"); +} + +void DenyAllParser::Accept(const XmlAttribute& /*attribute*/) +{ + ThrowMsg(Exception::ParseError, "There must not be any attribute"); +} + +void DenyAllParser::Accept(const Text& /*text*/) +{ + ThrowMsg(Exception::ParseError, "There must not be any text element"); +} diff --git a/src_mobile/configuration_parser/deny_all_parser.h b/src_mobile/configuration_parser/deny_all_parser.h new file mode 100644 index 0000000..d9dfe56 --- /dev/null +++ b/src_mobile/configuration_parser/deny_all_parser.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file deny_all_parser.h + * @author Lukasz Wrzosek (l.wrzosek@samsung.com) + * @version 0.1 + * @brief + */ +#ifndef DENY_ALL_PARSER_H +#define DENY_ALL_PARSER_H + +#include "element_parser.h" + +struct DenyAllParser : public ElementParser +{ + static ElementParserPtr Create(); + virtual void Accept(const Element& /*element*/); + virtual void Accept(const XmlAttribute& /*attribute*/); + virtual void Accept(const Text& /*text*/); + virtual void Verify() + {} + virtual ActionFunc GetElementParser(const DPL::String& ns, + const DPL::String& name); + + DenyAllParser(); +}; + +#endif // DENY_ALL_PARSER_H diff --git a/src_mobile/configuration_parser/element_parser.h b/src_mobile/configuration_parser/element_parser.h new file mode 100644 index 0000000..a44f94a --- /dev/null +++ b/src_mobile/configuration_parser/element_parser.h @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file element_parser.h + * @author Lukasz Wrzosek (l.wrzosek@samsung.com) + * @version 0.1 + * @brief + */ +#ifndef ELEMENT_PARSER_H_ +#define ELEMENT_PARSER_H_ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +struct XmlAttribute +{ + DPL::String prefix; + DPL::String name; + DPL::String value; + DPL::String ns; + DPL::String lang; +}; + +struct Element +{ + DPL::String name; + DPL::String value; + DPL::String ns; + DPL::String lang; +}; + +struct Text +{ + DPL::String value; + DPL::String ns; + DPL::String lang; +}; + +class ElementParser; + +typedef std::shared_ptr ElementParserPtr; + +class ElementParser : public std::enable_shared_from_this +{ + public: + class Exception + { + public: + DECLARE_EXCEPTION_TYPE(DPL::Exception, Base) + DECLARE_EXCEPTION_TYPE(Base, ParseError) + }; + typedef DPL::FastDelegate0 ActionFunc; + typedef std::map FuncMap; + + virtual void Accept(const Element&) = 0; + virtual void Accept(const XmlAttribute&) = 0; + virtual void Accept(const Text&) = 0; + virtual void Verify() = 0; + virtual ActionFunc GetElementParser(const DPL::String &ns, + const DPL::String &name) = 0; + virtual ~ElementParser() + {} + + protected: + ElementParser() + {} +}; + +#endif // ELEMENT_PARSER_H_ diff --git a/src_mobile/configuration_parser/ignoring_parser.cpp b/src_mobile/configuration_parser/ignoring_parser.cpp new file mode 100644 index 0000000..29520d5 --- /dev/null +++ b/src_mobile/configuration_parser/ignoring_parser.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file ignoring_parser.cpp + * @author Lukasz Wrzosek (l.wrzosek@samsung.com) + * @version 0.1 + * @brief + */ +#include "ignoring_parser.h" + +#include + +IgnoringParser::IgnoringParser() : ElementParser() +{} + +ElementParserPtr IgnoringParser::Create() +{ + return ElementParserPtr(new IgnoringParser()); +} + +ElementParserPtr IgnoringParser::Reuse() +{ + return shared_from_this(); +} + +ElementParser::ActionFunc IgnoringParser::GetElementParser(const DPL::String& /*ns*/, + const DPL::String& /*name*/) +{ + return DPL::MakeDelegate(this, &IgnoringParser::Reuse); +} + +void IgnoringParser::Accept(const Element& /*element*/) +{} + +void IgnoringParser::Accept(const Text& /*text*/) +{} + +void IgnoringParser::Accept(const XmlAttribute& /*attribute*/) +{} + +void IgnoringParser::Verify() +{} diff --git a/src_mobile/configuration_parser/ignoring_parser.h b/src_mobile/configuration_parser/ignoring_parser.h new file mode 100644 index 0000000..b14f1ad --- /dev/null +++ b/src_mobile/configuration_parser/ignoring_parser.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file ignoring_parser.h + * @author Lukasz Wrzosek (l.wrzosek@samsung.com) + * @version 0.1 + * @brief + */ +#ifndef IGNORING_PARSER_H_ +#define IGNORING_PARSER_H_ + +#include "element_parser.h" + +struct IgnoringParser : public ElementParser +{ + static ElementParserPtr Create(); + virtual ActionFunc GetElementParser(const DPL::String& ns, + const DPL::String& name); + virtual void Accept(const Element&); + virtual void Accept(const Text&); + virtual void Accept(const XmlAttribute&); + virtual void Verify(); + + IgnoringParser(); + + private: + ElementParserPtr Reuse(); +}; + +#endif // IGNORING_PARSER_H_ diff --git a/src_mobile/configuration_parser/libiriwrapper.cpp b/src_mobile/configuration_parser/libiriwrapper.cpp new file mode 100644 index 0000000..6d8de2a --- /dev/null +++ b/src_mobile/configuration_parser/libiriwrapper.cpp @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file libiriwrapper.cpp + * @author Piotr Marcinkiewicz (p.marcinkiew@samsung.com + * @version 0.1 + * @brief Libiri parser wrapper + */ +#include +#include +#include "libiriwrapper.h" + +//TODO: Design and implement new IRI manager class + +namespace LibIri { +Wrapper::Wrapper(const char* aIri) : m_Iri(iri_parse(aIri)) +{} +Wrapper::~Wrapper() +{ + iri_destroy(m_Iri); +} +//! \brief Returns true if iri is valid +bool Wrapper::Validate() +{ + return + m_Iri != NULL && + m_Iri->scheme != NULL && ( + m_Iri->display != NULL || + m_Iri->user != NULL || + m_Iri->auth != NULL || + m_Iri->password != NULL || + m_Iri->host != NULL || + m_Iri->path != NULL || + m_Iri->query != NULL || + m_Iri->anchor != NULL || + m_Iri->qparams != NULL || + m_Iri->schemelist != NULL); +} + +std::ostream & operator<<(std::ostream& a_stream, + const Wrapper& a_wrapper) +{ + iri_t& iri = *a_wrapper.m_Iri; +#define PRINT_FIELD(field) "] " #field " [" << (iri.field ? iri.field : "null") + a_stream << + " display [" << (iri.display ? iri.display : "null") << + PRINT_FIELD(scheme) << + PRINT_FIELD(user) << + PRINT_FIELD(auth) << + PRINT_FIELD(password) << + PRINT_FIELD(host) << + "] port [" << (iri.port ? iri.port : -1) << + PRINT_FIELD(path) << + PRINT_FIELD(query) << + PRINT_FIELD(anchor) << + "]"; + return a_stream; +#undef PRINT_FIELD +} +} //namespace LibIri diff --git a/src_mobile/configuration_parser/libiriwrapper.h b/src_mobile/configuration_parser/libiriwrapper.h new file mode 100644 index 0000000..b0b3e86 --- /dev/null +++ b/src_mobile/configuration_parser/libiriwrapper.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file libiriwrapper.cpp + * @author Piotr Marcinkiewicz (p.marcinkiew@samsung.com + * @version 0.1 + * @brief Libiri parser wrapper + */ + +#ifndef _WRT_ENGINE_SRC_INSTALLERCORE_CONFIGURATION_PARSER_LIBIRIWRAPPER_H_ +#define _WRT_ENGINE_SRC_INSTALLERCORE_CONFIGURATION_PARSER_LIBIRIWRAPPER_H_ + +#include +#include + +//TODO: Design and implement new IRI manager class +// +namespace LibIri { +struct Wrapper +{ + Wrapper(const char* aIri); + ~Wrapper(); + iri_t *m_Iri; + //! \brief Returns true if iri is valid + bool Validate(); +}; + +std::ostream & operator<<(std::ostream& a_stream, + const Wrapper& a_wrapper); +} //namespace LibIri + +#endif // _WRT_ENGINE_SRC_INSTALLERCORE_CONFIGURATION_PARSER_LIBIRIWRAPPER_H_ + diff --git a/src_mobile/configuration_parser/parser_runner.cpp b/src_mobile/configuration_parser/parser_runner.cpp new file mode 100644 index 0000000..725cd77 --- /dev/null +++ b/src_mobile/configuration_parser/parser_runner.cpp @@ -0,0 +1,462 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file parser_runner.cpp + * @author Lukasz Wrzosek (l.wrzosek@samsung.com) + * @version 0.1 + * @brief + */ +#include "parser_runner.h" +#include "root_parser.h" + +#include "stdio.h" + +#include +#include +#include +#include +#include + +#include + +class ParserRunner::Impl +{ + static void logErrorLibxml2(void *, const char *msg, ...) + { + char buffer[300]; + va_list args; + va_start(args, msg); + vsnprintf(buffer, 300, msg, args); + va_end(args); + _E("%s", buffer); + } + + static void logWarningLibxml2(void *, const char *msg, ...) + { + char buffer[300]; + va_list args; + va_start(args, msg); + vsnprintf(buffer, 300, msg, args); + va_end(args); + _W("%s", buffer); + } + + public: + bool Validate(const std::string& filename, const std::string& schema) + { + int ret = -1; + xmlSchemaParserCtxtPtr ctx; + xmlSchemaValidCtxtPtr vctx; + xmlSchemaPtr xschema; + ctx = xmlSchemaNewParserCtxt(schema.c_str()); + if (ctx == NULL) { + _E("xmlSchemaNewParserCtxt() Failed"); + return false; + } + xschema = xmlSchemaParse(ctx); + if (xschema == NULL) { + _E("xmlSchemaParse() Failed"); + return false; + } + vctx = xmlSchemaNewValidCtxt(xschema); + if (vctx == NULL) { + _E("xmlSchemaNewValidCtxt() Failed"); + return false; + } + xmlSchemaSetValidErrors(vctx, (xmlSchemaValidityErrorFunc)&logErrorLibxml2, (xmlSchemaValidityWarningFunc) &logWarningLibxml2, NULL); + ret = xmlSchemaValidateFile(vctx, filename.c_str(), 0); + if (ret == -1) { + _E("xmlSchemaValidateFile() failed"); + return false; + } else if (ret == 0) { + _E("Config is Valid"); + return true; + } else { + _E("Config Validation Failed with error code %d", ret); + return false; + } + return true; + } + + void Parse(const std::string& filename, + const ElementParserPtr& root) + { + DPL::FileInput input(filename); + Parse(&input, root); + } + + void Parse (DPL::AbstractInput *input, + const ElementParserPtr& root) + { + Try + { + m_reader = xmlReaderForIO(&IoRead, + &IoClose, + input, + NULL, + NULL, + XML_PARSE_NOENT); + + xmlTextReaderSetErrorHandler(m_reader, + &xmlTextReaderErrorHandler, + this); + xmlTextReaderSetStructuredErrorHandler( + m_reader, + &xmlTextReaderStructuredErrorHandler, + this); + SetCurrentElementParser(root); + + while (xmlTextReaderRead(m_reader) == 1) { + switch (xmlTextReaderNodeType(m_reader)) { + case XML_READER_TYPE_END_ELEMENT: + VerifyAndRemoveCurrentElementParser(); + break; + + case XML_READER_TYPE_ELEMENT: + { + // Elements without closing tag don't receive + // XML_READER_TYPE_END_ELEMENT event. + if (IsNoClosingTagElementLeft()) { + VerifyAndRemoveCurrentElementParser(); + } + + DPL::String elementName = GetNameWithoutNamespace(); + DPL::String nameSpace = GetNamespace(); + ElementParserPtr parser = GetCurrentElementParser(); + parser = parser->GetElementParser(nameSpace, + elementName) (); + Assert(!!parser); + SetCurrentElementParser(parser); + ParseNodeElement(parser); + break; + } + case XML_READER_TYPE_TEXT: + case XML_READER_TYPE_CDATA: + { + ParseNodeText(GetCurrentElementParser()); + break; + } + default: + _W("Ignoring Node of Type: %d", xmlTextReaderNodeType(m_reader)); + break; + } + + if (m_parsingError) { + _E("Parsing error occured: %ls", m_errorMsg.c_str()); + ThrowMsg(ElementParser::Exception::ParseError, m_errorMsg); + } + } + + if (m_parsingError) { + _E("Parsing error occured: %ls", m_errorMsg.c_str()); + ThrowMsg(ElementParser::Exception::ParseError, m_errorMsg); + } + + while (!m_stack.empty()) { + VerifyAndRemoveCurrentElementParser(); + } + } + Catch(ElementParser::Exception::Base) + { + CleanupParserRunner(); + _E("%s", _rethrown_exception.DumpToString().c_str()); + ReThrow(ElementParser::Exception::ParseError); + } + CleanupParserRunner(); + } + + Impl() : + m_reader(NULL), + m_parsingError(false) + {} + + ~Impl() + { + CleanupParserRunner(); + } + + private: + typedef std::stack ElementStack; + + private: + static void xmlTextReaderErrorHandler(void* arg, + const char* msg, + xmlParserSeverities /* severity */, + xmlTextReaderLocatorPtr /* locator */) + { + ParserRunner::Impl* impl = static_cast(arg); + impl->ErrorHandler(DPL::FromASCIIString(msg)); + } + + static void xmlTextReaderStructuredErrorHandler(void* arg, + xmlErrorPtr error) + { + ParserRunner::Impl* impl = static_cast(arg); + impl->StructuredErrorHandler(error); + } + + static int XMLCALL IoRead(void *context, + char *buffer, + int len) + { + DPL::AbstractInput *input = static_cast(context); + DPL::BinaryQueueAutoPtr data = input->Read(static_cast(len)); + if (!data.get()) { + return -1; + } + data->Flatten(buffer, data->Size()); + return static_cast(data->Size()); + } + + static int XMLCALL IoClose(void */* context */) + { + // NOOP + return 0; + } + + private: + void SetCurrentElementParser(const ElementParserPtr& elementParser) + { + Assert(elementParser); + + m_stack.push(elementParser); + } + + const ElementParserPtr& GetCurrentElementParser() const + { + Assert(!m_stack.empty()); + + return m_stack.top(); + } + + void VerifyAndRemoveCurrentElementParser() + { + Assert(!m_stack.empty()); + + m_stack.top()->Verify(); + m_stack.pop(); + } + + bool IsNoClosingTagElementLeft() const + { + Assert(m_reader); + + int depth = xmlTextReaderDepth(m_reader); + return (static_cast(m_stack.size()) - 2 == depth); + } + + void ParseNodeElement(const ElementParserPtr& parser) + { + Assert(m_reader); + + Element element; + element.value = GetValue(); + element.lang = GetLanguageTag(); + element.ns = GetNamespace(); + + _D("value: %ls, lang: %ls, ns: %ls)", + element.value.c_str(), element.lang.c_str(), element.ns.c_str()); + + parser->Accept(element); + ParseNodeElementAttributes(parser); + } + + void ParseNodeElementAttributes(const ElementParserPtr& parser) + { + Assert(m_reader); + int count = xmlTextReaderAttributeCount(m_reader); + for (int i = 0; i < count; ++i) { + xmlTextReaderMoveToAttributeNo(m_reader, i); + + XmlAttribute attribute; + attribute.ns = GetAttributeNamespace(); + attribute.prefix = GetNamePrefix(); + attribute.name = GetNameWithoutNamespace(); + attribute.value = GetValue(); + attribute.lang = GetLanguageTag(); + _D("Attribute name: %ls, value: %ls, prefix: %ls, namespace: %ls, lang: %ls", + attribute.name.c_str(), attribute.value.c_str(), attribute.prefix.c_str(), + attribute.ns.c_str(), attribute.lang.c_str()); + parser->Accept(attribute); + } + } + + void ParseNodeText(const ElementParserPtr& parser) + { + Text text; + text.value = GetValue(); + text.lang = GetLanguageTag(); + parser->Accept(text); + } + + DPL::String GetValue() const + { + DPL::String ret_value; + const xmlChar* value = xmlTextReaderConstValue(m_reader); + if (value) { + ret_value = + DPL::FromUTF8String(reinterpret_cast(value)); + } + + return ret_value; + } + + DPL::String GetAttributeValue(int pos) const + { + DPL::String ret_value; + const xmlChar* value = xmlTextReaderGetAttributeNo(m_reader, pos); + if (value) { + ret_value = + DPL::FromUTF8String(reinterpret_cast(value)); + } + xmlFree(const_cast(value)); + + return ret_value; + } + + DPL::String GetAttributeNamespace() const + { + DPL::String ret_value; + const xmlChar* value = xmlTextReaderLookupNamespace(m_reader, NULL); + if (value) { + ret_value = + DPL::FromUTF8String(reinterpret_cast(value)); + } + xmlFree(const_cast(value)); + + return ret_value; + } + + DPL::String GetName() const + { + DPL::String ret_value; + const xmlChar* value = xmlTextReaderConstName(m_reader); + if (value) { + ret_value = + DPL::FromUTF8String(reinterpret_cast(value)); + } + + return ret_value; + } + + DPL::String GetNamePrefix() const + { + DPL::String ret_value; + const xmlChar* value = xmlTextReaderPrefix(m_reader); + if (value) { + ret_value = + DPL::FromUTF8String(reinterpret_cast(value)); + } + + return ret_value; + } + + DPL::String GetNameWithoutNamespace() const + { + DPL::String ret_value; + const xmlChar* value = xmlTextReaderLocalName(m_reader); + if (value) { + ret_value = + DPL::FromUTF8String(reinterpret_cast(value)); + } + + return ret_value; + } + + DPL::String GetNamespace() const + { + DPL::String ret_value; + + const xmlChar* value = xmlTextReaderConstNamespaceUri(m_reader); + if (value) { + ret_value = + DPL::FromUTF8String(reinterpret_cast(value)); + } + + return ret_value; + } + + DPL::String GetLanguageTag() const + { + DPL::String ret_value; + const xmlChar* value = xmlTextReaderConstXmlLang(m_reader); + if (value) { + ret_value = + DPL::FromUTF8String(reinterpret_cast(value)); + } + + return ret_value; + } + + void ErrorHandler(const DPL::String& msg) + { + _E("LibXML: %ls", msg.c_str()); + m_parsingError = true; + m_errorMsg = m_errorMsg + DPL::FromASCIIString("\n"); + m_errorMsg = m_errorMsg + msg; + } + + void StructuredErrorHandler(xmlErrorPtr error) + { + _E("LibXML: %s", error->message); + m_parsingError = true; + m_errorMsg = m_errorMsg + DPL::FromASCIIString("\n"); + m_errorMsg = m_errorMsg + DPL::FromUTF8String(error->message); + } + + void CleanupParserRunner() + { + while (!m_stack.empty()) { + m_stack.pop(); + } + if (m_reader) { + xmlFreeTextReader(m_reader); + } + m_reader = NULL; + } + + private: + xmlTextReaderPtr m_reader; + ElementStack m_stack; + bool m_parsingError; + DPL::String m_errorMsg; +}; + +ParserRunner::ParserRunner() : + m_impl(new ParserRunner::Impl()) +{} + +bool ParserRunner::Validate(const std::string& filename, const std::string& schema) +{ + return m_impl->Validate(filename, schema); +} + +void ParserRunner::Parse(const std::string& filename, + ElementParserPtr root) +{ + m_impl->Parse(filename, root); +} + +void ParserRunner::Parse(DPL::AbstractInput *input, + ElementParserPtr root) +{ + m_impl->Parse(input, root); +} + +ParserRunner::~ParserRunner() +{ + delete m_impl; +} diff --git a/src_mobile/configuration_parser/parser_runner.h b/src_mobile/configuration_parser/parser_runner.h new file mode 100644 index 0000000..c5c0714 --- /dev/null +++ b/src_mobile/configuration_parser/parser_runner.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file parser_runner.h + * @author Lukasz Wrzosek (l.wrzosek@samsung.com) + * @version 0.1 + * @brief + */ +#ifndef PARSER_RUNNER_H_ +#define PARSER_RUNNER_H_ + +#include +#include +#include +#include "element_parser.h" + +class ParserRunner : private DPL::Noncopyable +{ + public: + bool Validate(const std::string& filename, const std::string& schema); + + void Parse(const std::string& filename, + ElementParserPtr root); + void Parse(DPL::AbstractInput *input, + ElementParserPtr root); + + ParserRunner(); + ~ParserRunner(); + + private: + class Impl; + Impl* m_impl; +}; + +#endif // PARSER_RUNNER_H_ + diff --git a/src_mobile/configuration_parser/root_parser.h b/src_mobile/configuration_parser/root_parser.h new file mode 100644 index 0000000..65bae87 --- /dev/null +++ b/src_mobile/configuration_parser/root_parser.h @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file root_parser.h + * @author Lukasz Wrzosek (l.wrzosek@samsung.com) + * @version 0.1 + * @brief + */ +#ifndef _WRT_ENGINE_SRC_INSTALLERCORE_CONFIGURATION_PARSER_ROOT_PARSER_H_ +#define _WRT_ENGINE_SRC_INSTALLERCORE_CONFIGURATION_PARSER_ROOT_PARSER_H_ + +#include +#include "element_parser.h" + +template +class RootParser : public ElementParser +{ + public: + typedef typename ta_Parser::Data Data; + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& name) + { + if (name == m_tag) { + return DPL::MakeDelegate(this, + &RootParser::OnWidgetElement); + } else { + ThrowMsg(Exception::ParseError, + name << " != " << m_tag); + } + } + + RootParser(Data data, + const DPL::String& tag) : + m_data(data), + m_tag(tag) + {} + + virtual ~RootParser() + {} + + virtual void Accept(const Element& /*element*/) + { + _D("element"); + } + + virtual void Accept(const XmlAttribute& /*attribute*/) + { + _D("attribute"); + } + + virtual void Accept(const Text& /*text*/) + { + _D("text"); + } + + virtual void Verify() + { + _D(""); + } + + private: + + ElementParserPtr OnWidgetElement() + { + typedef ta_Parser Parser; + return ElementParserPtr(new Parser(this->m_data)); + } + + Data m_data; + const DPL::String& m_tag; +}; + +#endif // _WRT_ENGINE_SRC_INSTALLERCORE_CONFIGURATION_PARSER_ROOT_PARSER_H_ diff --git a/src_mobile/configuration_parser/widget_parser.cpp b/src_mobile/configuration_parser/widget_parser.cpp new file mode 100644 index 0000000..e00b84e --- /dev/null +++ b/src_mobile/configuration_parser/widget_parser.cpp @@ -0,0 +1,2949 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * This file have been implemented in compliance with W3C WARP SPEC. + * but there are some patent issue between W3C WARP SPEC and APPLE. + * so if you want to use this file, refer to the README file in root directory + */ +/** + * @file widget_parser.cpp + * @author Lukasz Wrzosek (l.wrzosek@samsung.com) + * @version 0.1 + * @brief + */ +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +using namespace WrtDB; + +namespace Unicode { +static const DPL::String UTF_LRE = L"\x0202a"; +static const DPL::String UTF_LRO = L"\x0202d"; +static const DPL::String UTF_RLE = L"\x0202b"; +static const DPL::String UTF_RLO = L"\x0202e"; +static const DPL::String UTF_PDF = L"\x0202c"; + +Direction ParseDirAttribute(const XmlAttribute& attribute) +{ + Assert(L"dir" == attribute.name); + if (L"ltr" == attribute.value) { + return LRE; + } else if (L"rtl" == attribute.value) { + return RLE; + } else if (L"lro" == attribute.value) { + return LRO; + } else if (L"rlo" == attribute.value) { + return RLO; + } else { + _W("dir attribute has wrong value: %ls ", attribute.value.c_str()); + return EMPTY; + } +} + +void UpdateTextWithDirectionMark(Direction direction, + DPL::String* text) +{ + Assert(text); + switch (direction) { + case RLO: + *text = UTF_RLO + *text + UTF_PDF; + break; + case RLE: + *text = UTF_RLE + *text + UTF_PDF; + break; + case LRE: + *text = UTF_LRE + *text + UTF_PDF; + break; + case LRO: + *text = UTF_LRO + *text + UTF_PDF; + break; + case EMPTY: + break; + default: + Assert(false); + break; + } +} +} // namespace Unicode + +class InnerElementsParser : public ElementParser +{ + public: + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& /*name*/) + { + return DPL::MakeDelegate(this, &InnerElementsParser::Other); + } + + virtual void Accept(const Element& /*element*/) + {} + + virtual void Accept(const Text& text) + { + if (m_text.IsNull()) { + m_text = text; + } else { + m_text->value += text.value; + } + } + + virtual void Accept(const XmlAttribute& attribute) + { + if (attribute.name == L"dir") { + m_textDirection = Unicode::ParseDirAttribute(attribute); + } + } + + virtual void Verify() + { + if (!m_text.IsNull()) { + Unicode::UpdateTextWithDirectionMark(m_textDirection, + &m_text->value); + m_parentParser->Accept(*m_text); + } + } + + InnerElementsParser(ElementParserPtr parent) : + m_parentParser(parent), + m_textDirection(Unicode::EMPTY) + {} + + ElementParserPtr Other() + { + return ElementParserPtr(new InnerElementsParser( + std::static_pointer_cast( + shared_from_this()))); + } + + private: + DPL::Optional m_text; + ElementParserPtr m_parentParser; + Unicode::Direction m_textDirection; +}; + +class NameParser : public ElementParser +{ + public: + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& /*name*/) + { + return DPL::MakeDelegate(this, &NameParser::Other); + } + + virtual void Accept(const Element& element) + { + m_lang = element.lang; + m_name = L""; + } + + virtual void Accept(const Text& text) + { + if (m_name.IsNull()) { + m_name = text.value; + } else { + *m_name += text.value; + } + } + + virtual void Accept(const XmlAttribute& attribute) + { + if (attribute.name == L"short") { + if (m_shortName.IsNull()) { + m_shortName = attribute.value; + } + } else if (attribute.name == L"dir") { + m_textDirection = Unicode::ParseDirAttribute(attribute); + } + } + + virtual void Verify() + { + ConfigParserData::LocalizedData& data = m_data.localizedDataSet[m_lang]; + if (data.name.IsNull()) { + NormalizeString(m_name); + NormalizeString(m_shortName); + if (!m_name.IsNull()) { + Unicode::UpdateTextWithDirectionMark(m_textDirection, &*m_name); + } + data.name = m_name; + if (!m_shortName.IsNull()) { + Unicode::UpdateTextWithDirectionMark(m_textDirection, + &*m_shortName); + } + data.shortName = m_shortName; + } + } + + NameParser(Unicode::Direction direction, + ConfigParserData& data) : + m_data(data), + m_textDirection(direction) + {} + + ElementParserPtr Other() + { + return ElementParserPtr(new InnerElementsParser( + std::static_pointer_cast( + shared_from_this()))); + } + + private: + ConfigParserData& m_data; + DPL::OptionalString m_name; + DPL::OptionalString m_shortName; + DPL::OptionalString m_dir; + DPL::String m_lang; + Unicode::Direction m_textDirection; +}; + +class AccessParser : public ElementParser +{ + public: + enum StandardType + { + STANDARD_TYPE_NONE, + STANDARD_TYPE_WARP + }; + + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& /*name*/) + { + return DPL::MakeDelegate(this, &AccessParser::Other); + } + + virtual void Accept(const Element& element) + { + // for tizen web apps WARP should be used + if (element.ns == ConfigurationNamespace::W3CWidgetNamespaceName || + element.ns == ConfigurationNamespace::TizenWebAppNamespaceName) + { + m_standardType = STANDARD_TYPE_WARP; + } + } + + virtual void Accept(const Text& /*text*/) + {} + + void AcceptWac(const XmlAttribute& attribute) + { + if (attribute.name == L"origin") { + m_strIRIOrigin = attribute.value; + NormalizeString(m_strIRIOrigin); + } else if (attribute.name == L"subdomains") { + DPL::String normalizedValue = attribute.value; + NormalizeString(normalizedValue); + + if (normalizedValue == L"true") { + m_bSubDomainAccess = true; + } else if (normalizedValue == L"false") { + m_bSubDomainAccess = false; + } + } + } + + virtual void Accept(const XmlAttribute& attribute) + { + switch (m_standardType) { + case STANDARD_TYPE_WARP: + AcceptWac(attribute); + break; + default: + _E("Error in Access tag - unknown standard."); + break; + } + } + + void VerifyWac() + { + WarpIRI iri; + iri.set(m_strIRIOrigin, false); + + if (!iri.isAccessDefinition()) { + _W("Access list element: %ls is not acceptable by WARP standard and will be ignored!", + m_strIRIOrigin.c_str()); + return; + } + + if(m_strIRIOrigin == L"*") //wildcard match means yes for subdomains + { + m_bSubDomainAccess = true; + } + + ConfigParserData::AccessInfo accessInfo(m_strIRIOrigin, + m_bSubDomainAccess); + //std::pair ret = + m_data.accessInfoSet.insert(accessInfo); + } + + virtual void Verify() + { + switch (m_standardType) { + case STANDARD_TYPE_WARP: + VerifyWac(); + break; + default: + _E("Error in Access tag - unknown standard."); + break; + } + } + + AccessParser(ConfigParserData& data) : + ElementParser(), + m_bSubDomainAccess(false), + m_standardType(STANDARD_TYPE_NONE), + m_network(false), + m_data(data) + {} + + ElementParserPtr Other() + { + return ElementParserPtr(new InnerElementsParser( + ElementParserPtr(shared_from_this()))); + } + + private: + DPL::String m_strIRIOrigin; + bool m_bSubDomainAccess; + StandardType m_standardType; + bool m_network; + ConfigParserData& m_data; +}; + +class DescriptionParser : public ElementParser +{ + public: + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& /*name*/) + { + return DPL::MakeDelegate(this, &DescriptionParser::Other); + } + + virtual void Accept(const Element& element) + { + m_lang = element.lang; + m_description = L""; + } + + ElementParserPtr Other() + { + return ElementParserPtr(new InnerElementsParser( + std::static_pointer_cast( + shared_from_this()))); + } + + virtual void Accept(const Text& text) + { + if (m_description.IsNull()) { + m_description = text.value; + } else { + *m_description += text.value; + } + } + + virtual void Accept(const XmlAttribute& attribute) + { + if (attribute.name == L"dir") { + m_textDirection = Unicode::ParseDirAttribute(attribute); + } + } + + virtual void Verify() + { + ConfigParserData::LocalizedData& data = m_data.localizedDataSet[m_lang]; + if (data.description.IsNull()) { + if (!m_description.IsNull()) { + Unicode::UpdateTextWithDirectionMark(m_textDirection, + &*m_description); + } + data.description = m_description; + } + } + + DescriptionParser(Unicode::Direction direction, + ConfigParserData& data) : + m_data(data), + m_lang(), + m_description(), + m_textDirection(direction) + {} + + private: + ConfigParserData& m_data; + DPL::String m_lang; + DPL::OptionalString m_description; + Unicode::Direction m_textDirection; +}; + +class AuthorParser : public ElementParser +{ + public: + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& /*name*/) + { + return DPL::MakeDelegate(this, &AuthorParser::Other); + } + + AuthorParser(Unicode::Direction direction, + ConfigParserData& data) : + m_data(data), + m_textDirection(direction) + {} + + virtual void Accept(const Element& /*element*/) + { + m_authorName = L""; + } + + virtual void Accept(const Text& text) + { + *(m_authorName) += text.value; + } + + virtual void Accept(const XmlAttribute& attribute) + { + if (attribute.name == L"href") { + //Validate href IRI and ignore it if invalid + //See also test: ta-argMozRiC-an + LibIri::Wrapper iri(DPL::ToUTF8String(attribute.value).c_str()); + if (iri.Validate()) { + m_authorHref = attribute.value; + } + } else if (attribute.name == L"email") { + m_authorEmail = attribute.value; + } else if (attribute.name == L"dir") { + m_textDirection = Unicode::ParseDirAttribute(attribute); + } + } + + virtual void Verify() + { + if (!m_data.authorName && !m_data.authorHref && !m_data.authorEmail) { + NormalizeString(m_authorName); + NormalizeString(m_authorHref); + NormalizeString(m_authorEmail); + if (!!m_authorName) { + Unicode::UpdateTextWithDirectionMark(m_textDirection, + &*m_authorName); + m_data.authorName = m_authorName; + } + if (!!m_authorHref) { + m_data.authorHref = m_authorHref; + } + if (!!m_authorEmail) { + m_data.authorEmail = m_authorEmail; + } + } + } + + ElementParserPtr Other() + { + return ElementParserPtr(new InnerElementsParser( + std::static_pointer_cast( + shared_from_this()))); + } + + private: + ConfigParserData& m_data; + DPL::OptionalString m_authorEmail; + DPL::OptionalString m_authorHref; + DPL::OptionalString m_authorName; + Unicode::Direction m_textDirection; +}; + +class LicenseParser : public ElementParser +{ + public: + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& /*name*/) + { + return DPL::MakeDelegate(this, &LicenseParser::Other); + } + + LicenseParser(Unicode::Direction direction, + ConfigParserData& data) : + m_data(data), + m_ignore(true), + m_textDirection(direction) + {} + + virtual void Accept(const Element& element) + { + if (m_license.IsNull()) { + m_lang = element.lang; + m_license = L""; + m_ignore = false; + } + } + + virtual void Accept(const Text& text) + { + if (!m_ignore) { + *m_license += text.value; + } + } + + virtual void Accept(const XmlAttribute& attribute) + { + if (!m_ignore) { + if (attribute.name == L"href" && m_licenseHref.IsNull()) { + m_licenseHref = attribute.value; + } else if (attribute.name == L"file" && m_licenseFile.IsNull()) { + m_licenseFile = attribute.value; + } else if (attribute.name == L"dir") { + m_textDirection = Unicode::ParseDirAttribute(attribute); + } + } + } + + virtual void Verify() + { + ConfigParserData::LocalizedData& data = m_data.localizedDataSet[m_lang]; + if (data.license.IsNull()) { + if (!m_license.IsNull()) { + Unicode::UpdateTextWithDirectionMark(m_textDirection, + &*m_license); + } + data.license = m_license; + data.licenseHref = m_licenseHref; + data.licenseFile = m_licenseFile; + } + } + + ElementParserPtr Other() + { + return ElementParserPtr(new InnerElementsParser( + ElementParserPtr(shared_from_this()))); + } + + private: + ConfigParserData& m_data; + DPL::String m_lang; + bool m_ignore; + + DPL::OptionalString m_license; + DPL::OptionalString m_licenseFile; + DPL::OptionalString m_licenseHref; + Unicode::Direction m_textDirection; +}; + +class IconParser : public ElementParser +{ + DECLARE_EXCEPTION_TYPE(ElementParser::Exception::ParseError, BadSrcError) + + public: + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& /*name*/) + { + return &IgnoringParser::Create; //ignore unknown according to w3c + } + + IconParser(ConfigParserData& data) : ElementParser(), + m_data(data) + {} + + virtual void Accept(const Element& /*element*/) + {} + + virtual void Accept(const XmlAttribute& attribute) + { + if (attribute.name == L"src") { + if (attribute.value.size() > 0) { + m_src = attribute.value; + } + } else if (attribute.name == L"width") { + m_width = ParseSizeAttributeValue(attribute.value); + } else if (attribute.name == L"height") { + m_height = ParseSizeAttributeValue(attribute.value); + } + } + + virtual void Accept(const Text& /*text*/) + { + ThrowMsg(Exception::ParseError, "Icon element must be empty"); + } + + virtual void Verify() + { + if (m_src.IsNull()) { + _W("src attribute of icon element is mandatory - ignoring"); + return; + } + + Try + { + ConfigParserData::Icon icon(delocalizeSrcPath(*m_src)); + icon.width = m_width; + icon.height = m_height; + + ConfigParserData::IconsList::iterator it = std::find( + m_data.iconsList.begin(), m_data.iconsList.end(), icon); + if (it == m_data.iconsList.end()) { + m_data.iconsList.push_front(icon); + } + } + Catch(BadSrcError) + { + _W("src attribute is invalid: %ls", (*m_src).c_str()); + } + } + + private: + ConfigParserData& m_data; + DPL::OptionalString m_src; + DPL::OptionalInt m_width; + DPL::OptionalInt m_height; + + static DPL::OptionalInt ParseSizeAttributeValue(const DPL::String& value) + { + DPL::OptionalString normalizedValue = value; + NormalizeString(normalizedValue); + if (!(*normalizedValue).empty()) { + char* reterr = NULL; + errno = 0; + long int valueInt = + strtol(DPL::ToUTF8String(value).c_str(), &reterr, 10); + if (errno != 0 || + std::string(reterr) == DPL::ToUTF8String(value) || + valueInt <= 0) + { + return DPL::OptionalInt::Null; + } else { + return valueInt; + } + } + return DPL::OptionalInt::Null; + } + + /** + * @brief delocalizePath removes locales folder from relative path if + * neccessary + * @param source source string + * + * @throw BadSrcError if string is bad value of src attribute + * + * @return corrected string + */ + static DPL::String delocalizeSrcPath(const DPL::String & source) + { + static const DPL::String localeFolder(L"locales/"); + static const int index = localeFolder.size(); + + DPL::String result = source; + + if (source.substr(0, index) == localeFolder) { + size_t pos = result.find_first_of('/', index); + if (pos != std::string::npos && pos + 1 < source.size()) { + result = result.substr(pos + 1, source.size()); + } else { + Throw(BadSrcError); + } + } + return result; + } +}; + +class ContentParser : public ElementParser +{ + public: + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& /*name*/) + { + return &IgnoringParser::Create; //ignore unknown according to w3c + } + + ContentParser(ConfigParserData& data) : + ElementParser(), + m_data(data) + {} + + virtual void Accept(const Element& element) + { + m_namespace = element.ns; + } + + virtual void Accept(const Text& /*text*/) + {} + + virtual void Accept(const XmlAttribute& attribute) + { + DPL::String value = attribute.value; + NormalizeString(value); + + if (attribute.name == L"src") { + m_src = value; + } else if (attribute.name == L"type") { + m_type = value; + MimeTypeUtils::MimeAttributes mimeAttributes = + MimeTypeUtils::getMimeAttributes(value); + if ((mimeAttributes.count(L"charset") > 0) && m_encoding.IsNull()) + { + m_encoding = mimeAttributes[L"charset"]; + } + } else if (attribute.name == L"encoding") { + if (!value.empty()) { + m_encoding = value; + } + } + } + + virtual void Verify() + { + if(!!m_data.startFileEncountered) + { + if(m_data.startFileNamespace == m_namespace + || m_namespace != ConfigurationNamespace::TizenWebAppNamespaceName) + { + return; + } + //else continue -> if previous item was not in tizen namespace + } + + m_data.startFileEncountered = true; + m_data.startFileNamespace = m_namespace; + + //we're consciously setting startFile even if m_src is null or invalid. + //WidgetConfigurationManager will deal with this. + m_data.startFile = m_src; + + if (!!m_src) { + m_data.startFileContentType = m_type; + if (!!m_encoding) { + m_data.startFileEncoding = m_encoding; + } else { + m_data.startFileEncoding = L"UTF-8"; + } + } + } + + private: + DPL::OptionalString m_src; + DPL::OptionalString m_type; + DPL::OptionalString m_encoding; + ConfigParserData& m_data; + DPL::String m_namespace; +}; + +class PreferenceParser : public ElementParser +{ + public: + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& /*name*/) + { + return &IgnoringParser::Create; //ignore unknown according to w3c + } + + virtual void Accept(const XmlAttribute& attribute) + { + if (attribute.name == L"name") { + m_name = attribute.value; + } else if (attribute.name == L"value") { + m_value = attribute.value; + } else if (attribute.name == L"readonly") { + if (attribute.value == L"true") { + m_required = true; + } else { + m_required = false; + } + } + } + + virtual void Accept(const Element& /*element*/) + {} + + virtual void Accept(const Text& /*text*/) + { + ThrowMsg(Exception::ParseError, "param element must be empty"); + } + + virtual void Verify() + { + if (m_name.IsNull()) { + _W("preference element must have name attribute"); + return; + } + NormalizeString(m_name); + NormalizeString(m_value); + ConfigParserData::Preference preference(*m_name, m_required); + preference.value = m_value; + if (m_data.preferencesList.find(preference) == + m_data.preferencesList.end()) + { + m_data.preferencesList.insert(preference); + } + } + + PreferenceParser(ConfigParserData& data) : + ElementParser(), + m_required(false), + m_data(data) + {} + + private: + DPL::OptionalString m_name; + DPL::OptionalString m_value; + bool m_required; + ConfigParserData& m_data; +}; + +class SettingParser : public ElementParser +{ + public: + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& /*name*/) + { + return &IgnoringParser::Create; //ignore unknown according to w3c + } + + virtual void Accept(const Text& /*text*/) + {} + + virtual void Accept(const Element& /*element*/) + {} + + virtual void Accept(const XmlAttribute& attribute) + { + m_setting.m_name = attribute.name; + m_setting.m_value = attribute.value; + m_data.settingsList.insert(m_setting); + } + + virtual void Verify() + {} + + SettingParser(ConfigParserData& data) : + ElementParser(), + m_data(data), + m_setting(L"", L"") + {} + + private: + ConfigParserData& m_data; + ConfigParserData::Setting m_setting; +}; + +class AppControlParser : public ElementParser +{ + public: + struct SourceParser : public ElementParser + { + public: + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& /*name*/) + { + return &IgnoringParser::Create; //ignore unknown according to w3c + } + + virtual void Accept(const Text& /*text*/) + {} + + virtual void Accept(const Element& /*element*/) + {} + + virtual void Accept(const XmlAttribute& attribute) + { + if (attribute.name == L"name") { + if (attribute.value.size() > 0) { + m_value = attribute.value; + NormalizeString(m_value); + } + } + } + + virtual void Verify() + { + if (m_value.IsNull() || *m_value == L"") { + return; + } + + m_data.m_src = *m_value; + } + + SourceParser(ConfigParserData::AppControlInfo& data) : + ElementParser(), + m_properNamespace(false), + m_data(data) + {} + + private: + bool m_properNamespace; + DPL::OptionalString m_value; + ConfigParserData::AppControlInfo& m_data; + }; + + struct OperationParser : public ElementParser + { + public: + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& /*name*/) + { + return &IgnoringParser::Create; //ignore unknown according to w3c + } + + virtual void Accept(const Text& /*text*/) + {} + + virtual void Accept(const Element& /*element*/) + {} + + virtual void Accept(const XmlAttribute& attribute) + { + if (attribute.name == L"name") { + if (attribute.value.size() > 0) { + m_value = attribute.value; + NormalizeString(m_value); + } + } + } + + virtual void Verify() + { + if (m_value.IsNull() || *m_value == L"") { + return; + } + + m_data.m_operation = *m_value; + } + + OperationParser(ConfigParserData::AppControlInfo& data) : + ElementParser(), + m_properNamespace(false), + m_data(data) + {} + + private: + bool m_properNamespace; + DPL::OptionalString m_value; + ConfigParserData::AppControlInfo& m_data; + }; + + struct UriParser : public ElementParser + { + public: + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& /*name*/) + { + return &IgnoringParser::Create; //ignore unknown according to w3c + } + + virtual void Accept(const Text& /*text*/) + {} + + virtual void Accept(const Element& /*element*/) + {} + + virtual void Accept(const XmlAttribute& attribute) + { + if (attribute.name == L"name") { + if (attribute.value.size() > 0) { + m_value = attribute.value; + NormalizeString(m_value); + } + } + } + + virtual void Verify() + { + // exception + DPL::String ignoreUri(L"file"); + + if (!m_value.IsNull() && *m_value == ignoreUri) + { + _D("exception : '%ls' scheme will be ignored.", (*m_value).c_str()); + m_value = DPL::OptionalString::Null; + } + + if (m_value.IsNull() || *m_value == L"") { + return; + } + + DPL::String wildString(L"*/*"); + if ((m_data.m_uriList.find(wildString) == m_data.m_uriList.end()) + && (m_data.m_uriList.find(*m_value) == m_data.m_uriList.end())) + { + m_data.m_uriList.insert(*m_value); + } else { + _D("Ignoring uri with name %ls", (*m_value).c_str()); + } + } + + UriParser(ConfigParserData::AppControlInfo& data) : + ElementParser(), + m_properNamespace(false), + m_data(data) + {} + + private: + bool m_properNamespace; + DPL::OptionalString m_value; + ConfigParserData::AppControlInfo& m_data; + }; + + struct MimeParser : public ElementParser + { + public: + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& /*name*/) + { + return &IgnoringParser::Create; //ignore unknown according to w3c + } + + virtual void Accept(const Text& /*text*/) + {} + + virtual void Accept(const Element& /*element*/) + {} + + virtual void Accept(const XmlAttribute& attribute) + { + if (attribute.name == L"name") { + if (attribute.value.size() > 0) { + m_value = attribute.value; + NormalizeString(m_value); + } + } + } + + virtual void Verify() + { + if (m_value.IsNull() || *m_value == L"") { + return; + } + + DPL::String wildString(L"*/*"); + if ((m_data.m_mimeList.find(wildString) == + m_data.m_mimeList.end()) + && (m_data.m_mimeList.find(*m_value) == + m_data.m_mimeList.end())) + { + m_data.m_mimeList.insert(*m_value); + } else { + _D("Ignoring mime with name %ls", (*m_value).c_str()); + } + } + + MimeParser(ConfigParserData::AppControlInfo& data) : + ElementParser(), + m_properNamespace(false), + m_data(data) + {} + + private: + bool m_properNamespace; + DPL::OptionalString m_value; + ConfigParserData::AppControlInfo& m_data; + }; + + struct DispositionParser : public ElementParser + { + public: + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& /*name*/) + { + return &IgnoringParser::Create; + } + + virtual void Accept(const Text& /*text*/) + {} + + virtual void Accept(const Element& /*element*/) + {} + + virtual void Accept(const XmlAttribute& attribute) + { + if (attribute.name == L"name") { + if (attribute.value.size() > 0) { + m_value = attribute.value; + NormalizeString(m_value); + } + } + } + + virtual void Verify() + { + if (m_value.IsNull() || *m_value == L"") { + return; + } + + DPL::String windowString(L"window"); + DPL::String inlineString(L"inline"); + + if (*m_value == L"window") { + m_data.m_disposition = + ConfigParserData::AppControlInfo::Disposition::WINDOW; + } else if (*m_value == L"inline") { + m_data.m_disposition = + ConfigParserData::AppControlInfo::Disposition::INLINE; + } else { + _D("Ignoring dispostion value %ls", (*m_value).c_str()); + } + } + + DispositionParser(ConfigParserData::AppControlInfo& data) : + ElementParser(), + m_properNamespace(false), + m_data(data) + {} + + private: + bool m_properNamespace; + DPL::OptionalString m_value; + ConfigParserData::AppControlInfo& m_data; + }; + + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& name) + { + if (name == L"src") { + return DPL::MakeDelegate(this, &AppControlParser::OnSourceElement); + } else if (name == L"operation") { + return DPL::MakeDelegate(this, + &AppControlParser::OnOperationElement); + } else if (name == L"uri") { + return DPL::MakeDelegate(this, &AppControlParser::OnUriElement); + } else if (name == L"mime") { + return DPL::MakeDelegate(this, &AppControlParser::OnMimeElement); + } else if (name == L"disposition") { + return DPL::MakeDelegate(this, + &AppControlParser::OnDispositionElement); + } else { + return &IgnoringParser::Create; //ignore unknown according to w3c + } + } + + virtual void Accept(const XmlAttribute& /*attribute*/) + {} + + virtual void Accept(const Element& element) + { + _W("namespace for app service = %ls", element.ns.c_str()); + if (element.ns == ConfigurationNamespace::W3CWidgetNamespaceName) { + ThrowMsg(Exception::ParseError, + "Wrong xml namespace for widget element"); + } + } + + virtual void Accept(const Text& /*text*/) + { + ThrowMsg(Exception::ParseError, "param element must be empty"); + } + + virtual void Verify() + { + if (m_appControl.m_src == L"") { + ThrowMsg(Exception::ParseError, "service element must have src element"); + } + + if (m_appControl.m_operation == L"") { + ThrowMsg(Exception::ParseError, "service element must have operation element"); + } + + auto res = std::find(m_data.appControlList.begin(), m_data.appControlList.end(), m_appControl); + if(res != m_data.appControlList.end()) { + ThrowMsg(Exception::ParseError, "service element must be unique"); + } + +#ifdef NFC_EXCEPTION_HANDLING_FOR_TIZEN_2_2_ONLY + // XXX This feature should be retained to Tizen 2.2 only. + // NFC exception handling which was requested from Tizen Device API team. + + const DPL::String exceptionNfcOperation = + L"http://tizen.org/appcontrol/operation/nfc/transaction"; + const DPL::String exceptionNfcUri = L"nfc://secure/aid/"; + const DPL::String divertingNfcUri1 = L"nfc://secure/SIM1/aid/"; + const DPL::String divertingNfcUri2 = L"nfc://secure/eSE/aid/"; + + if (m_appControl.m_operation == exceptionNfcOperation + && m_appControl.m_mimeList.empty() + && m_appControl.m_uriList.size() == 1 + && (m_appControl.m_uriList.begin())->compare(0, exceptionNfcUri.length(), exceptionNfcUri) == 0) + { + DPL::String originalUri = *m_appControl.m_uriList.begin(); + DPL::String newUri = originalUri; + + newUri.replace(0, exceptionNfcUri.length(), divertingNfcUri1); + m_appControl.m_uriList.erase(m_appControl.m_uriList.begin()); + m_appControl.m_uriList.insert(newUri); + m_data.appControlList.push_back(m_appControl); + _D("NFC exception : %ls -> %ls", originalUri.c_str(), newUri.c_str()); + + newUri = originalUri; + newUri.replace(0, exceptionNfcUri.length(), divertingNfcUri2); + m_appControl.m_uriList.erase(m_appControl.m_uriList.begin()); + m_appControl.m_uriList.insert(newUri); + m_data.appControlList.push_back(m_appControl); + _D("NFC exception : %ls -> %ls", originalUri.c_str(), newUri.c_str()); + + return; + } +#endif // NFC_EXCEPTION_HANDLING_FOR_TIZEN_2_2_ONLY + + m_data.appControlList.push_back(m_appControl); + } + + ElementParserPtr OnSourceElement() + { + return ElementParserPtr(new SourceParser(m_appControl)); + } + + ElementParserPtr OnOperationElement() + { + return ElementParserPtr(new OperationParser(m_appControl)); + } + + ElementParserPtr OnUriElement() + { + return ElementParserPtr(new UriParser(m_appControl)); + } + + ElementParserPtr OnMimeElement() + { + return ElementParserPtr(new MimeParser(m_appControl)); + } + + ElementParserPtr OnDispositionElement() + { + return ElementParserPtr(new DispositionParser(m_appControl)); + } + + AppControlParser(ConfigParserData& data) : + ElementParser(), + m_data(data), + m_appControl(L"") + {} + + private: + ConfigParserData& m_data; + ConfigParserData::AppControlInfo m_appControl; +}; + +class ApplicationParser : public ElementParser +{ + public: + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& /*name*/) + { + return &IgnoringParser::Create; //ignore unknown according to w3c + } + + virtual void Accept(const Text& /*text*/) + { + if (m_properNamespace) { + ThrowMsg(Exception::ParseError, "application element must be empty"); + } + } + + virtual void Accept(const Element& element) + { + if (element.ns == + ConfigurationNamespace::TizenWebAppNamespaceName) + { + m_properNamespace = true; + } + } + + virtual void Accept(const XmlAttribute& attribute) + { + if (m_properNamespace) { + if (attribute.name == L"id") { + m_id = attribute.value; + NormalizeAndTrimSpaceString(m_id); + } else if (attribute.name == L"package") { + m_package = attribute.value; + } else if (attribute.name == L"required_version") { + m_version = attribute.value; + NormalizeString(m_version); + } else { + ThrowMsg(Exception::ParseError, + "unknown attribute '" + + DPL::ToUTF8String(attribute.name) + + "' in application element"); + } + } + } + + virtual void Verify() + { + VerifyIdAndPackage(); + VerifyVersion(); + } + + ApplicationParser(ConfigParserData& data) : + ElementParser(), + m_data(data), + m_id(DPL::OptionalString::Null), + m_version(DPL::OptionalString::Null), + m_properNamespace(false) + {} + + static const char* const REGEXP_ID; + + private: + void VerifyIdAndPackage() + { + if (!m_package) + { + ThrowMsg(Exception::ParseError, + "application element must have package attribute"); + } + else + { + pcrecpp::RE re(REGEXP_PACKAGE); + if (!re.FullMatch(DPL::ToUTF8String(*m_package))) + { + ThrowMsg(Exception::ParseError, + "invalid format of package attribute"); + } + } + + if (!m_id) { + ThrowMsg(Exception::ParseError, + "application element must have id attribute"); + } + else + { + std::string package; + pcrecpp::RE re(REGEXP_ID); + if (!re.FullMatch(DPL::ToUTF8String(*m_id), &package)) + { + ThrowMsg(Exception::ParseError, + "invalid format of id attribute"); + } + if (package != DPL::ToUTF8String(*m_package)) + { + ThrowMsg(Exception::ParseError, + "invalid package prefix in id attribute"); + } + } + + m_data.tizenAppId = m_id; + m_data.tizenPkgId = m_package; + } + + void VerifyVersion() + { + if (!m_version) + { + ThrowMsg(Exception::ParseError, + "application element must have required_version attribute"); + } + else + { + pcrecpp::RE re(REGEXP_VERSION); + if (!re.FullMatch(DPL::ToUTF8String(*m_version))) + { + ThrowMsg(Exception::ParseError, + "invalid format of version attribute"); + } + } + + m_data.tizenMinVersionRequired = m_version; + } + + static const char* const REGEXP_PACKAGE; + static const char* const REGEXP_VERSION; + + ConfigParserData& m_data; + DPL::OptionalString m_id; + DPL::OptionalString m_package; + DPL::OptionalString m_version; + bool m_properNamespace; +}; + +const char* const ApplicationParser::REGEXP_PACKAGE = "[0-9A-Za-z]{10}"; +const char* const ApplicationParser::REGEXP_ID = "([0-9A-Za-z]{10})\\.[0-9A-Za-z]{1,52}"; +const char* const ApplicationParser::REGEXP_VERSION = "\\d+\\.\\d+(\\.\\d+)?"; + +class SplashParser : public ElementParser +{ + public: + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& /*name*/) + { + return &IgnoringParser::Create; //ignore unknown according to w3c + } + + virtual void Accept(const XmlAttribute& attribute) + { + if (m_properNamespace) + { + if (attribute.name == L"src") { + if (attribute.value.size() > 0) { + m_src = attribute.value; + } + } + } + } + + virtual void Accept(const Element& element) + { + if (element.ns == + ConfigurationNamespace::TizenWebAppNamespaceName) + { + m_properNamespace = true; + } + } + + virtual void Accept(const Text& /*text*/) + {} + + virtual void Verify() + { + if (m_src.IsNull()) + { + _W("src attribute of splash element is mandatory - ignoring"); + return; + } + + m_data.splashImgSrc = m_src; + } + + SplashParser(ConfigParserData& data) : + ElementParser(), + m_data(data), + m_properNamespace(false) + {} + + private: + DPL::OptionalString m_src; + ConfigParserData& m_data; + bool m_properNamespace; +}; + +class BackgroundParser : public ElementParser +{ + public: + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& /*name*/) + { + return &IgnoringParser::Create; //ignore unknown according to w3c + } + + virtual void Accept(const XmlAttribute& attribute) + { + if (attribute.name == L"src") { + if (attribute.value.size() > 0) { + m_src = attribute.value; + } + } + } + + virtual void Accept(const Element& /*element*/) + {} + + virtual void Accept(const Text& /*text*/) + {} + + virtual void Verify() + { + if (m_src.IsNull()) { + _W("src attribute of background element is mandatory - ignoring"); + return; + } + + m_data.backgroundPage = m_src; + } + + explicit BackgroundParser(ConfigParserData& data) : + m_data(data) + {} + + private: + DPL::OptionalString m_src; + ConfigParserData& m_data; +}; + +class PrivilegeParser : public ElementParser +{ + public: + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& /*name*/) + { + return &IgnoringParser::Create; //ignore unknown according to w3c + } + + virtual void Accept(const Text& /*text*/) + {} + + virtual void Accept(const Element& element) + { + if (element.ns == + ConfigurationNamespace::TizenWebAppNamespaceName) + { + m_properNamespace = true; + } + _D("element"); + } + + virtual void Accept(const XmlAttribute& attribute) + { + if (m_properNamespace) { + if (attribute.name == L"name") { + m_feature.name = attribute.value; + m_privilege.name = attribute.value; + } + } + } + + virtual void Verify() + { + LibIri::Wrapper iri(DPL::ToUTF8String(m_feature.name).c_str()); + + if (m_feature.name != L"") { + if (iri.Validate()) { + if (m_data.featuresList.find(m_feature) == + m_data.featuresList.end()) + { + m_data.featuresList.insert(m_feature); + } else { + _D("Ignoring feature with name %ls", m_feature.name.c_str()); + } + } + } + + LibIri::Wrapper iriPrivilege( + DPL::ToUTF8String(m_privilege.name).c_str()); + + if (m_privilege.name != L"") { + if (iriPrivilege.Validate()) { + if (m_data.privilegeList.find(m_privilege) == + m_data.privilegeList.end()) + { + m_data.privilegeList.insert(m_privilege); + } else { + _D("Ignoring privilege with name %ls", m_privilege.name.c_str()); + } + } + } + } + + PrivilegeParser(ConfigParserData& data) : + ElementParser(), + m_data(data), + m_feature(L""), + m_privilege(L""), + m_properNamespace(false) + {} + + private: + ConfigParserData& m_data; + ConfigParserData::Feature m_feature; + ConfigParserData::Privilege m_privilege; + bool m_properNamespace; +}; + +class CategoryParser : public ElementParser +{ + public: + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& /*name*/) + { + return &IgnoringParser::Create; //ignore unknown according to w3c + } + + virtual void Accept(const XmlAttribute& attribute) + { + if (attribute.name == L"name") { + if (attribute.value.size() > 0) { + m_name = attribute.value; + } + } + } + + virtual void Accept(const Element& /*element*/) + {} + + virtual void Accept(const Text& /*text*/) + {} + + virtual void Verify() + { + if (m_name.IsNull()) { + _W("name attribute of category element is mandatory - ignoring"); + return; + } + + if (m_data.categoryList.find(*m_name) == + m_data.categoryList.end()) + { + m_data.categoryList.insert(*m_name); + } + } + + explicit CategoryParser(ConfigParserData& data) : + m_data(data) + {} + + private: + DPL::OptionalString m_name; + ConfigParserData& m_data; +}; + +class AppWidgetParser : public ElementParser +{ + public: + + struct BoxLabelParser : public ElementParser + { + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& /*name*/) + { + return &IgnoringParser::Create; //ignore unknown according to w3c + } + + virtual void Accept(const XmlAttribute& attribute) + { + if (m_properNamespace) { + m_lang = attribute.lang; + } + } + virtual void Accept(const Element& element) + { + if (element.ns == + ConfigurationNamespace::TizenWebAppNamespaceName) + { + m_properNamespace = true; + } + } + + virtual void Accept(const Text& text) + { + if (m_properNamespace) { + m_label = text.value; + } + } + + virtual void Verify() + { + std::pair boxLabel; + if (m_label.empty()) { + _W("box-label element is empty"); + boxLabel.first = DPL::FromUTF8String(""); + boxLabel.second = DPL::FromUTF8String(""); + m_data.m_label.push_back(boxLabel); + } + else { + boxLabel.first = m_lang; + boxLabel.second = m_label; + m_data.m_label.push_back(boxLabel); + } + } + + BoxLabelParser(ConfigParserData::LiveboxInfo& data) : + ElementParser(), + m_properNamespace(false), + m_data(data) + {} + + private: + DPL::String m_lang; + DPL::String m_label; + bool m_properNamespace; + ConfigParserData::LiveboxInfo& m_data; + }; + + struct BoxIconParser : public ElementParser + { + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& /*name*/) + { + return &IgnoringParser::Create; //ignore unknown according to w3c + } + + virtual void Accept(const XmlAttribute& attribute) + { + if (m_properNamespace) { + if (attribute.name == L"src") { + m_icon = attribute.value; + } + } + } + + virtual void Accept(const Element& element) + { + if (element.ns == + ConfigurationNamespace::TizenWebAppNamespaceName) + { + m_properNamespace = true; + } + } + + virtual void Accept(const Text& /*text*/) + {} + + virtual void Verify() + { + if (m_icon.empty()) { + ThrowMsg(Exception::ParseError, + "src attribute of box-icon element is mandatory - ignoring"); + } + if (!m_data.m_icon.empty()) { + ThrowMsg(Exception::ParseError, + " element should occur as 0 or 1 time"); + } + m_data.m_icon = m_icon; + } + + explicit BoxIconParser(ConfigParserData::LiveboxInfo& data) : + ElementParser(), + m_properNamespace(false), + m_data(data) + {} + + private: + DPL::String m_icon; + bool m_properNamespace; + ConfigParserData::LiveboxInfo& m_data; + }; + + struct BoxContentParser : public ElementParser + { + struct BoxSizeParser : public ElementParser + { + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& /*name*/) + { + return &IgnoringParser::Create; //ignore unknown according to w3c + } + + virtual void Accept(const XmlAttribute& attribute) + { + if (m_properNamespace) { + if (attribute.name == L"preview") { + m_preview = attribute.value; + } + if (attribute.name == L"use-decoration") { + m_useDecoration = attribute.value; + } + } + } + + virtual void Accept(const Element& element) + { + if (element.ns == + ConfigurationNamespace::TizenWebAppNamespaceName) + { + m_properNamespace = true; + } + } + + virtual void Accept(const Text& text) + { + if (m_properNamespace) { + m_size = text.value; + } + } + + virtual void Verify() + { + if(m_size.empty()) { + ThrowMsg(Exception::ParseError, + "size is mandatory - ignoring"); + } + + ConfigParserData::LiveboxInfo::BoxSizeInfo boxSizeInfo; + boxSizeInfo.m_size = m_size; + boxSizeInfo.m_preview = m_preview; + boxSizeInfo.m_useDecoration = m_useDecoration; + m_data.m_boxSize.push_back(boxSizeInfo); + } + + explicit BoxSizeParser( + ConfigParserData::LiveboxInfo::BoxContentInfo& data) : + ElementParser(), + m_properNamespace(false), + m_data(data) + {} + + private: + DPL::String m_size; + DPL::String m_preview; + DPL::String m_useDecoration; + bool m_properNamespace; + ConfigParserData::LiveboxInfo::BoxContentInfo& m_data; + }; + + struct PdParser : public ElementParser + { + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& /*name*/) + { + return &IgnoringParser::Create; //ignore unknown according to w3c + } + + virtual void Accept(const XmlAttribute& attribute) + { + if (m_properNamespace) { + if (attribute.name == L"src") { + m_src = attribute.value; + } else if (attribute.name == L"width") { + m_width = attribute.value; + } else if (attribute.name == L"height") { + m_height = attribute.value; + } else if (attribute.name == L"fast-open") { + m_fastOpen= attribute.value; + } + } + } + + virtual void Accept(const Element& element) + { + if (element.ns == + ConfigurationNamespace::TizenWebAppNamespaceName) + { + m_properNamespace = true; + } + } + + virtual void Accept(const Text& /*text*/) + {} + + virtual void Verify() + { + if (m_src.empty()) { + ThrowMsg(Exception::ParseError, + "src attribute of pd element is mandatory - ignoring"); + } + + if (m_width.empty()) { + ThrowMsg(Exception::ParseError, + "width attribute of pd element is mandatory - ignoring"); + } + + if (m_height.empty()) { + ThrowMsg(Exception::ParseError, + "height attribute of pd element is mandatory - ignoring"); + } + + if (ConvertToInt(m_width).IsNull()) { + ThrowMsg(Exception::ParseError, + "width attribute of pd element cannot be converted to int - ignoring. value: " << m_width); + } + + + DPL::OptionalInt height = ConvertToInt(m_height); + + if (height.IsNull()) { + ThrowMsg(Exception::ParseError, + "height attribute of pd element cannot be converted to int - ignoring. value: " << m_height); + } + + if (*height < 1) { + m_height = L"1"; + _D("height attribute of pd element shouldn't be less than 1. Changed to 1 from %d", *height); + } else if (*height > 380){ + m_height = L"380"; + _D("height attribute of pd element shouldn't be greater than 380. Changed to 380 from %d", *height); + } + + m_data.m_pdSrc = m_src; + m_data.m_pdWidth = m_width; + m_data.m_pdHeight = m_height; + m_data.m_pdFastOpen = m_fastOpen; + } + + explicit PdParser( + ConfigParserData::LiveboxInfo::BoxContentInfo& data) : + ElementParser(), + m_properNamespace(false), + m_data(data) + {} + + private: + DPL::OptionalInt ConvertToInt(const DPL::String& intAsString) + { + char * endptr; + std::string tempStr = DPL::ToUTF8String(intAsString); + const char * intAsString_c = tempStr.c_str(); + errno = 0; + long int intAsString_i = strtol(intAsString_c, &endptr, 10); + + if ((errno == ERANGE && (intAsString_i == LONG_MAX || intAsString_i == LONG_MIN)) + || intAsString_i > INT_MAX || intAsString_i < INT_MIN + || *endptr != '\0') { + return DPL::OptionalInt::Null; + } + + return static_cast(intAsString_i); + } + + DPL::String m_src; + DPL::String m_width; + DPL::String m_height; + DPL::String m_fastOpen; + + bool m_properNamespace; + ConfigParserData::LiveboxInfo::BoxContentInfo& m_data; + }; + + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& name) + { + if (name == L"box-size") { + return DPL::MakeDelegate( + this, + &AppWidgetParser::BoxContentParser:: + OnBoxSizeElement); + } else if (name == L"pd") { + return DPL::MakeDelegate( + this, + &AppWidgetParser::BoxContentParser:: + OnPdElement); + } else { + ThrowMsg(Exception::ParseError, + "No element parser for name: " << name); + } + } + + virtual void Accept(const XmlAttribute& attribute) + { + if (m_properNamespace) { + if (attribute.name == L"src") { + m_box.m_boxSrc = attribute.value; + } + if (attribute.name == L"mouse-event") { + m_box.m_boxMouseEvent = attribute.value; + } + if (attribute.name == L"touch-effect") { + m_box.m_boxTouchEffect = attribute.value; + } + } + } + + virtual void Accept(const Element& element) + { + if (element.ns == + ConfigurationNamespace::TizenWebAppNamespaceName) + { + m_properNamespace = true; + } + } + + virtual void Accept(const Text& /*text*/) + {} + + virtual void Verify() + { + if (m_box.m_boxSrc.empty()) { + ThrowMsg(Exception::ParseError, + "src attribute of box-content element is mandatory - ignoring"); + } + + if (!m_box.m_boxMouseEvent.empty() && + CheckIfNotTrueNorFalse(m_box.m_boxMouseEvent)) + { + ThrowMsg(Exception::ParseError, + "mouse-event attribute of box-content element should be true or false - ignoring"); + } + + if (!m_box.m_boxTouchEffect.empty() && + CheckIfNotTrueNorFalse(m_box.m_boxTouchEffect)) + { + ThrowMsg(Exception::ParseError, + "touch-effect attribute of box-content element should be true or false - ignoring"); + } + + if (m_box.m_boxMouseEvent.empty()) { + m_box.m_boxMouseEvent = L"false"; + } + + if (m_box.m_boxTouchEffect.empty()) { + m_box.m_boxTouchEffect = L"true"; + } + + if (m_box.m_boxSize.empty()) { + ThrowMsg(Exception::ParseError, + "box-size element of box-content element not found - ignoring"); + } + + m_data.m_boxInfo = m_box; + } + + explicit BoxContentParser(ConfigParserData::LiveboxInfo& data) : + ElementParser(), + m_properNamespace(false), + m_data(data) + {} + + ElementParserPtr OnBoxSizeElement() + { + return ElementParserPtr(new BoxSizeParser(m_box)); + } + + ElementParserPtr OnPdElement() + { + return ElementParserPtr(new PdParser(m_box)); + } + + private: + bool m_properNamespace; + ConfigParserData::LiveboxInfo& m_data; + ConfigParserData::LiveboxInfo::BoxContentInfo m_box; + }; + + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& name) + { + if (name == L"box-label") { + return DPL::MakeDelegate(this, &AppWidgetParser::OnBoxLabelElement); + } else if (name == L"box-icon") { + return DPL::MakeDelegate(this, &AppWidgetParser::OnBoxIconElement); + } else if (name == L"box-content") { + return DPL::MakeDelegate(this, &AppWidgetParser::OnBoxContentElement); + } else { + return &IgnoringParser::Create; //ignore unknown according to w3c + } + } + + virtual void Accept(const XmlAttribute& attribute) + { + if (m_properNamespace) { + if (attribute.name == L"id") { + m_liveboxId = attribute.value; + } else if (attribute.name == L"primary") { + m_primary = attribute.value; + } else if (attribute.name == L"auto-launch") { + m_autoLaunch = attribute.value; + } else if (attribute.name == L"update-period") { + m_updatePeriod = attribute.value; + } else if (attribute.name == L"type") { + m_type = attribute.value; + } + } + } + + virtual void Accept(const Element& element) + { + if (element.ns == + ConfigurationNamespace::TizenWebAppNamespaceName) + { + m_properNamespace = true; + } + } + + virtual void Accept(const Text& /*text*/) + {} + + virtual void Verify() + { + if (m_liveboxId.empty()) { + ThrowMsg(Exception::ParseError, + "app-widget element must have id attribute"); + } + else + { + pcrecpp::RE re(REGEXP_ID_STRING.c_str()); + if (!re.FullMatch(DPL::ToUTF8String(m_liveboxId))) + { + ThrowMsg(Exception::ParseError, + "invalid format of app-widget id attribute"); + } + } + + if (m_primary.empty()) + { + ThrowMsg(Exception::ParseError, + "app-widget element must have primary attribute"); + } else if (CheckIfNotTrueNorFalse(m_primary)) + { + ThrowMsg(Exception::ParseError, + "auto-launch attribute of app-widget element should be true or false - ignoring"); + } + + if (!m_autoLaunch.empty() && + CheckIfNotTrueNorFalse(m_autoLaunch)) + { + ThrowMsg(Exception::ParseError, + "auto-launch attribute of app-widget element should be true or false - ignoring"); + } + + if (!m_updatePeriod.empty()) + { + char * endptr; + errno = 0; + std::string tempStr = DPL::ToUTF8String(m_updatePeriod); + + //set standard locale to fix decimal point mark - '.' + std::string currentLocale = setlocale(LC_NUMERIC, NULL); + if (NULL == setlocale(LC_NUMERIC, "C")) + _W("Failed to change locale to \"C\""); + double updatePeriod = strtod(tempStr.c_str(), &endptr); + + //go back to previous locale + if (NULL == setlocale(LC_NUMERIC, currentLocale.c_str())) + _W("Failed to set previous locale"); + + if ((errno == ERANGE && (updatePeriod == -HUGE_VAL || updatePeriod == HUGE_VAL)) + || *endptr != '\0') { + ThrowMsg(Exception::ParseError, + "update-period attribute of app-widget element should be a number - ignoring. current value: " << m_updatePeriod); + } else if (updatePeriod < 1800.0) { + _D("update-period attribute of app-widget element shouldn't be less than 1800.0 - changed to 1800 from value: %ls", m_updatePeriod.c_str()); + m_updatePeriod = L"1800.0"; + } + } + + if (m_autoLaunch.empty()) { + m_autoLaunch = L"false"; + } + + if(m_livebox.m_label.empty()) { + ThrowMsg(Exception::ParseError, + "box-label element of app-widget element not found - ignoring"); + } + + if(!m_boxContentFound) { + ThrowMsg(Exception::ParseError, + "box-content element of app-widget element not found - ignoring"); + } + + m_livebox.m_liveboxId = m_liveboxId; + m_livebox.m_primary = m_primary; + m_livebox.m_autoLaunch = m_autoLaunch; + m_livebox.m_updatePeriod = m_updatePeriod; + m_livebox.m_type = m_type; + + m_data.m_livebox.push_back(m_livebox); + } + + explicit AppWidgetParser(ConfigParserData& data) : + ElementParser(), + m_data(data), + m_properNamespace(false), + m_boxContentFound(false) + { + m_livebox = ConfigParserData::LiveboxInfo(); + } + + ElementParserPtr OnBoxLabelElement() + { + + return ElementParserPtr(new BoxLabelParser(m_livebox)); + } + + ElementParserPtr OnBoxIconElement() + { + return ElementParserPtr(new BoxIconParser(m_livebox)); + } + + ElementParserPtr OnBoxContentElement() + { + m_boxContentFound = true; + return ElementParserPtr(new BoxContentParser(m_livebox)); + } + + private: + static std::string REGEXP_ID_STRING; + ConfigParserData& m_data; + ConfigParserData::LiveboxInfo m_livebox; + DPL::String m_liveboxId; + DPL::String m_primary; + DPL::String m_autoLaunch; + DPL::String m_updatePeriod; + DPL::String m_type; + bool m_properNamespace; + bool m_boxContentFound; + + static bool CheckIfNotTrueNorFalse(const DPL::String &stringToCheck) + { + return stringToCheck.compare(L"true") != 0 && stringToCheck.compare(L"false") != 0; + } +}; + +std::string AppWidgetParser::REGEXP_ID_STRING = std::string(ApplicationParser::REGEXP_ID) + "\\.[0-9A-Za-z]+"; + +class AllowNavigationParser : public ElementParser +{ + public: + AllowNavigationParser(ConfigParserData& data) : + ElementParser(), + m_data(data), + m_properNamespace(false) + {} + + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& /*name*/) + { + return &IgnoringParser::Create; //ignore unknown according to w3c + } + + virtual void Accept(const Element& element) + { + if (element.ns == ConfigurationNamespace::TizenWebAppNamespaceName) { + m_properNamespace = true; + } + } + + virtual void Accept(const Text& text) + { + if (m_properNamespace) + { + m_origin = text.value; + } + } + + virtual void Accept(const XmlAttribute& /*attribute*/) + { + } + + virtual void Verify() + { + if (m_data.allowNavigationEncountered || !m_properNamespace) + { + return; + } + m_data.allowNavigationEncountered = true; + + if (m_origin.IsNull()) { + _W("data is empty"); + return; + } + + char* data = strdup(DPL::ToUTF8String(*m_origin).c_str()); + char* ptr = strtok(data," "); + while (ptr != NULL) { + std::string origin = ptr; + ptr = strtok(NULL," "); + if(origin == "*") { + ConfigParserData::AllowNavigationInfo info(L"*", L"*"); + m_data.allowNavigationInfoList.push_back(info); + continue; + } + + std::unique_ptr iri(iri_parse(origin.c_str()), iri_destroy); + if (!iri->host || strlen(iri->host) == 0) { + // input origin should has schem and host + // in case of file scheme path is filled + // "http://" + _W("input origin isn't verified"); + continue; + } + DPL::String scheme = L"*"; + if (iri->scheme && strlen(iri->scheme) != 0) { + scheme = DPL::FromUTF8String(iri->scheme); + } + ConfigParserData::AllowNavigationInfo info( + scheme, + DPL::FromUTF8String(iri->host)); + m_data.allowNavigationInfoList.push_back(info); + } + free(data); + } + + private: + DPL::OptionalString m_origin; + ConfigParserData& m_data; + bool m_properNamespace; +}; + +class CspParser : public ElementParser +{ + public: + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& /*name*/) + { + return &IgnoringParser::Create; //ignore unknown according to w3c + } + + CspParser(ConfigParserData& data) : + ElementParser(), + m_data(data), + m_properNamespace(false) + {} + + virtual void Accept(const Element& element) + { + if (element.ns == ConfigurationNamespace::TizenWebAppNamespaceName) { + m_properNamespace = true; + } + } + + virtual void Accept(const XmlAttribute& /*attribute*/) + {} + + virtual void Accept(const Text& text) + { + if (m_properNamespace) { + m_policy = text.value; + } + } + + virtual void Verify() + { + if (!m_policy.IsNull()) { + m_data.cspPolicy = *m_policy; + } + } + + private: + ConfigParserData& m_data; + bool m_properNamespace; + DPL::OptionalString m_policy; +}; + +class CspReportOnlyParser : public ElementParser +{ + public: + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& /*name*/) + { + return &IgnoringParser::Create; //ignore unknown according to w3c + } + + CspReportOnlyParser(ConfigParserData& data) : + ElementParser(), + m_data(data), + m_properNamespace(false) + {} + + virtual void Accept(const Element& element) + { + if (element.ns == ConfigurationNamespace::TizenWebAppNamespaceName) { + m_properNamespace = true; + } + } + + virtual void Accept(const XmlAttribute& /*attribute*/) + {} + + virtual void Accept(const Text& text) + { + if (m_properNamespace) { + m_policy = text.value; + } + } + + virtual void Verify() + { + if (!m_policy.IsNull()) { + m_data.cspPolicyReportOnly = *m_policy; + } + } + + private: + ConfigParserData& m_data; + bool m_properNamespace; + DPL::OptionalString m_policy; +}; + +class AccountParser : public ElementParser +{ + public: + struct IconParser : public ElementParser + { + public: + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& /*name*/) + { + return &IgnoringParser::Create; //ignore unknown according to w3c + } + + virtual void Accept(const Text& text) + { + if (text.value == L"") { + return; + } + m_value = text.value; + } + + virtual void Accept(const Element& /*element*/) + {} + + virtual void Accept(const XmlAttribute& attribute) + { + if (attribute.name == L"section") { + if (attribute.value == L"Account") { + m_type = ConfigParserData::IconSectionType::DefaultIcon; + } else if (attribute.value == L"AccountSmall") { + m_type = ConfigParserData::IconSectionType::SmallIcon; + } + } + } + + virtual void Verify() + { + if (m_value.IsNull() || *m_value == L"") { + return; + } + + std::pair icon; + icon.first = m_type; + icon.second = *m_value; + + m_data.m_iconSet.insert(icon); + } + + IconParser(ConfigParserData::AccountProvider& data) : + ElementParser(), + m_properNamespace(false), + m_type(ConfigParserData::DefaultIcon), + m_data(data) + {} + + private: + bool m_properNamespace; + ConfigParserData::IconSectionType m_type; + ConfigParserData::AccountProvider& m_data; + DPL::OptionalString m_value; + }; + + struct DisplayNameParser : public ElementParser + { + public: + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& /*name*/) + { + return &IgnoringParser::Create; //ignore unknown according to w3c + } + + virtual void Accept(const Text& text) + { + if (text.value == L"") { + return; + } + m_value = text.value; + } + + virtual void Accept(const Element& element) + { + m_lang = element.lang; + m_value= L""; + } + + virtual void Accept(const XmlAttribute& /*attribute*/) + {} + + virtual void Verify() + { + if (m_value.IsNull() || *m_value == L"") { + return; + } + + std::pair name; + name.first = *m_lang; + name.second = *m_value; + + m_data.m_displayNameSet.insert(name); + } + + DisplayNameParser(ConfigParserData::AccountProvider& data) : + ElementParser(), + m_properNamespace(false), + m_data(data) + {} + + private: + bool m_properNamespace; + DPL::OptionalString m_lang; + DPL::OptionalString m_value; + ConfigParserData::AccountProvider& m_data; + }; + + struct CapabilityParser : public ElementParser + { + public: + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& /*name*/) + { + return &IgnoringParser::Create; //ignore unknown according to w3c + } + + virtual void Accept(const Text& text) + { + if (text.value == L"") { + return; + } + m_value = text.value; + } + + virtual void Accept(const Element& /*element*/) + {} + + virtual void Accept(const XmlAttribute& /*attribute*/) + {} + + virtual void Verify() + { + if (m_value.IsNull() || *m_value == L"") { + return; + } + m_data.m_capabilityList.push_back(*m_value); + } + + CapabilityParser(ConfigParserData::AccountProvider& data) : + ElementParser(), + m_properNamespace(false), + m_data(data) + {} + + private: + bool m_properNamespace; + DPL::OptionalString m_value; + ConfigParserData::AccountProvider& m_data; + }; + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& name) + { + if (name == L"icon") { + return DPL::MakeDelegate(this, &AccountParser::OnIconElement); + } else if (name == L"display-name") { + return DPL::MakeDelegate(this, + &AccountParser::OnDisplayNameElement); + } else if (name == L"capability") { + return DPL::MakeDelegate(this, &AccountParser::OnCapabilityElement); + } else { + return &IgnoringParser::Create; //ignore unknown according to w3c + } + } + + virtual void Accept(const Text& /*text*/) + {} + + virtual void Accept(const Element& /*element*/) + {} + + virtual void Accept(const XmlAttribute& attribute) + { + if (attribute.name == L"multiple-account-support") { + if (attribute.value == L"true") { + m_account.m_multiAccountSupport = true; + } + } + } + + virtual void Verify() + { + } + + ElementParserPtr OnIconElement() + { + return ElementParserPtr(new IconParser(m_account)); + } + + ElementParserPtr OnDisplayNameElement() + { + return ElementParserPtr(new DisplayNameParser(m_account)); + } + + ElementParserPtr OnCapabilityElement() + { + return ElementParserPtr(new CapabilityParser(m_account)); + } + + AccountParser(ConfigParserData& data) : + ElementParser(), + m_properNamespace(false), + m_multiSupport(false), + m_data(data), + m_account(data.accountProvider) + { + } + + private: + bool m_properNamespace; + bool m_multiSupport; + ConfigParserData& m_data; + ConfigParserData::AccountProvider& m_account; +}; + +class MetadataParser : public ElementParser +{ + public: + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& /*name*/) + { + return &IgnoringParser::Create; //ignore unknown according to w3c + } + + virtual void Accept(const XmlAttribute& attribute) + { + if (m_properNamespace) { + if (attribute.name == L"key") { + m_key = attribute.value; + } else if (attribute.name == L"value") { + m_value = attribute.value; + } + } + } + + virtual void Accept(const Element& element) + { + if (element.ns == ConfigurationNamespace::TizenWebAppNamespaceName) { + m_properNamespace = true; + } + } + + virtual void Accept(const Text& /*text*/) + { + ThrowMsg(Exception::ParseError, "param element must be empty"); + } + + virtual void Verify() + { + if (m_key.IsNull()) { + _W("metadata element must have key attribute"); + return; + } + NormalizeString(m_key); + NormalizeString(m_value); + ConfigParserData::Metadata metaData(m_key, m_value); + FOREACH(it, m_data.metadataList) { + if (!DPL::StringCompare(*it->key, *m_key)) { + _E("Key isn't unique"); + return; + } + } + m_data.metadataList.push_back(metaData); + } + + MetadataParser(ConfigParserData& data) : + ElementParser(), + m_data(data), + m_properNamespace(false) + {} + + private: + DPL::OptionalString m_key; + DPL::OptionalString m_value; + ConfigParserData& m_data; + bool m_properNamespace; +}; + +ElementParser::ActionFunc WidgetParser::GetElementParser( + const DPL::String& /*ns*/, + const DPL::String& name) +{ + FuncMap::const_iterator it = m_map.find(name); + if (it != m_map.end()) { + return it->second; + } else { + return &IgnoringParser::Create; //ignore unknown according to w3c + } +} + +WidgetParser::WidgetParser(ConfigParserData& data) : + m_data(data), + m_textDirection(Unicode::EMPTY) +{ + m_map[L"name"] = DPL::MakeDelegate(this, &WidgetParser::OnNameElement); + m_map[L"access"] = DPL::MakeDelegate(this, &WidgetParser::OnAccessElement); + m_map[L"description"] = + DPL::MakeDelegate(this, &WidgetParser::OnDescriptionElement); + m_map[L"author"] = DPL::MakeDelegate(this, &WidgetParser::OnAuthorElement); + m_map[L"license"] = + DPL::MakeDelegate(this, &WidgetParser::OnLicenseElement); + m_map[L"icon"] = DPL::MakeDelegate(this, &WidgetParser::OnIconElement); + m_map[L"content"] = + DPL::MakeDelegate(this, &WidgetParser::OnContentElement); + m_map[L"preference"] = + DPL::MakeDelegate(this, &WidgetParser::OnPreferenceElement); + m_map[L"setting"] = + DPL::MakeDelegate(this, &WidgetParser::OnSettingElement); + m_map[L"application"] = DPL::MakeDelegate( + this, + &WidgetParser:: + OnApplicationElement); + m_map[L"splash"] = DPL::MakeDelegate(this, &WidgetParser::OnSplashElement); + m_map[L"background"] = DPL::MakeDelegate(this, + &WidgetParser::OnBackgroundElement); + m_map[L"privilege"] = DPL::MakeDelegate(this, + &WidgetParser::OnPrivilegeElement); + m_map[L"app-control"] = DPL::MakeDelegate( + this, + &WidgetParser:: + OnAppControlElement); + m_map[L"category"] = DPL::MakeDelegate(this, + &WidgetParser::OnCategoryElement); + m_map[L"app-widget"] = DPL::MakeDelegate(this, &WidgetParser::OnAppWidgetElement); +#ifdef CSP_ENABLED + m_map[L"content-security-policy"] = DPL::MakeDelegate( + this, + &WidgetParser:: + OnCspElement); + m_map[L"content-security-policy-report-only"] = DPL::MakeDelegate( + this, + &WidgetParser:: + OnCspReportOnlyElement); +#endif +#ifdef ALLOW_NAVIGATION_ENABLED + m_map[L"allow-navigation"] = + DPL::MakeDelegate(this, &WidgetParser::OnAllowNavigationElement); +#endif + m_map[L"account"] = DPL::MakeDelegate(this, &WidgetParser::OnAccountElement); + m_map[L"metadata"] = DPL::MakeDelegate(this, &WidgetParser::OnMetadataElement); +} + +ElementParserPtr WidgetParser::OnNameElement() +{ + return ElementParserPtr(new NameParser(m_textDirection, m_data)); +} + +ElementParserPtr WidgetParser::OnAccessElement() +{ + return ElementParserPtr(new AccessParser(m_data)); +} + +ElementParserPtr WidgetParser::OnDescriptionElement() +{ + return ElementParserPtr(new DescriptionParser(m_textDirection, m_data)); +} + +ElementParserPtr WidgetParser::OnAuthorElement() +{ + return ElementParserPtr(new AuthorParser(m_textDirection, m_data)); +} + +ElementParserPtr WidgetParser::OnLicenseElement() +{ + return ElementParserPtr(new LicenseParser(m_textDirection, m_data)); +} + +ElementParserPtr WidgetParser::OnIconElement() +{ + return ElementParserPtr(new IconParser(m_data)); +} + +ElementParserPtr WidgetParser::OnContentElement() +{ + return ElementParserPtr(new ContentParser(m_data)); +} + +ElementParserPtr WidgetParser::OnPreferenceElement() +{ + return ElementParserPtr(new PreferenceParser(m_data)); +} + +ElementParserPtr WidgetParser::OnSettingElement() +{ + return ElementParserPtr(new SettingParser(m_data)); +} + +ElementParserPtr WidgetParser::OnApplicationElement() +{ + return ElementParserPtr(new ApplicationParser(m_data)); +} + +ElementParserPtr WidgetParser::OnSplashElement() +{ + return ElementParserPtr(new SplashParser(m_data)); +} + +ElementParserPtr WidgetParser::OnBackgroundElement() +{ + return ElementParserPtr(new BackgroundParser(m_data)); +} + +ElementParserPtr WidgetParser::OnPrivilegeElement() +{ + return ElementParserPtr(new PrivilegeParser(m_data)); +} + +ElementParserPtr WidgetParser::OnAppControlElement() +{ + return ElementParserPtr(new AppControlParser(m_data)); +} + +ElementParserPtr WidgetParser::OnCategoryElement() +{ + return ElementParserPtr(new CategoryParser(m_data)); +} + +ElementParserPtr WidgetParser::OnAppWidgetElement() +{ + return ElementParserPtr(new AppWidgetParser(m_data)); +} + +ElementParserPtr WidgetParser::OnCspElement() +{ + return ElementParserPtr(new CspParser(m_data)); +} + +ElementParserPtr WidgetParser::OnCspReportOnlyElement() +{ + return ElementParserPtr(new CspReportOnlyParser(m_data)); +} + +ElementParserPtr WidgetParser::OnAllowNavigationElement() +{ + return ElementParserPtr(new AllowNavigationParser(m_data)); +} + +ElementParserPtr WidgetParser::OnAccountElement() +{ + return ElementParserPtr(new AccountParser(m_data)); +} + +ElementParserPtr WidgetParser::OnMetadataElement() +{ + return ElementParserPtr(new MetadataParser(m_data)); +} + +void WidgetParser::Accept(const Element& element) +{ + if (element.ns != ConfigurationNamespace::W3CWidgetNamespaceName && + element.ns != ConfigurationNamespace::TizenWebAppNamespaceName) + { + ThrowMsg(Exception::ParseError, + "Wrong xml namespace for widget element"); + } +} + +void WidgetParser::Accept(const Text& /*text*/) +{ + ThrowMsg(Exception::ParseError, "widged element must be empty"); +} + +void WidgetParser::Accept(const XmlAttribute& attribute) +{ + if (attribute.name == L"id") { + LibIri::Wrapper iri(DPL::ToUTF8String(attribute.value).c_str()); + //If may important tests starts to fail this test we will have + //to consider commenting this test out again. + if (iri.Validate()) { + m_data.widget_id = attribute.value; + NormalizeString(m_data.widget_id); + } else { + _W("Widget id validation failed: %ls", attribute.value.c_str()); + } + } else if (attribute.name == L"version") { + m_version = attribute.value; + NormalizeString(m_version); + } else if (attribute.name == L"min-version") { + _D("min-version attribute was found. Value: %ls", attribute.value.c_str()); + m_minVersion = attribute.value; + NormalizeString(m_minVersion); + m_data.minVersionRequired = m_minVersion; + } else if (attribute.name == L"height") { + DPL::OptionalString value = attribute.value; + NormalizeString(value); + std::string v = DPL::ToUTF8String(*value); + + if (!v.empty()) { + unsigned char c = v.c_str()[0]; + if (isdigit(c)) { + int val = 0; + for (size_t i = 0; i < v.size(); ++i) { + c = v.c_str()[i]; + if (isdigit(c)) { + val *= 10; + val += (c - '0'); + } else { + break; + } + } + m_data.height = val; + } + } + } else if (attribute.name == L"width") { + DPL::OptionalString value = attribute.value; + NormalizeString(value); + std::string v = DPL::ToUTF8String(*value); + + if (!v.empty()) { + unsigned char c = v.c_str()[0]; + if (c >= '0' && c <= '9') { + int val = 0; + for (size_t i = 0; i < v.size(); ++i) { + c = v.c_str()[i]; + if (c >= '0' && c <= '9') { + val *= 10; + val += (c - '0'); + } else { + break; + } + } + m_data.width = val; + } + } + } else if (attribute.name == L"viewmodes") { + DPL::Tokenize(attribute.value, + L" ", + std::inserter(m_windowModes, + m_windowModes.end()), + true); + } else if (attribute.name == L"dir") { + m_textDirection = Unicode::ParseDirAttribute(attribute); + } else if (L"defaultlocale" == attribute.name) { + if (!m_defaultlocale) { + m_defaultlocale = attribute.value; + NormalizeString(m_defaultlocale); + std::string dl = DPL::ToUTF8String(*m_defaultlocale); + + if (!LanguageSubtagRstTreeSingleton::Instance(). + ValidateLanguageTag(dl)) { + _W("Language tag: %s is not valid", dl.c_str()); + m_defaultlocale = DPL::OptionalString::Null; + } else { + _D("Default locale found %s", dl.c_str()); + } + } else { + _W("Ignoring subsequent default locale"); + } + //Any other value consider as a namespace definition + } else if (attribute.name == L"xmlns" || attribute.prefix == L"xmlns") { + _D("Namespace domain: %ls", attribute.name.c_str()); + _D("Namespace value: %ls", attribute.value.c_str()); + m_nameSpaces[attribute.name] = attribute.value; + } else { + _E("Unknown attirbute: namespace=%ls, name=%ls, value=%ls", + attribute.ns.c_str(), attribute.name.c_str(), attribute.value.c_str()); + } +} + +void WidgetParser::Verify() +{ + FOREACH(mode, m_windowModes) { + if (L"windowed" == *mode || L"floating" == *mode || + L"fullscreen" == *mode || L"maximized" == *mode || + L"minimized" == *mode) + { + m_data.windowModes.insert(*mode); + } + } + if (!m_version.IsNull()) { + Unicode::UpdateTextWithDirectionMark(m_textDirection, &*m_version); + m_data.version = m_version; + } + m_data.defaultlocale = m_defaultlocale; + FOREACH(ns, m_nameSpaces) { + m_data.nameSpaces.insert(ns->second); + } +} + diff --git a/src_mobile/configuration_parser/widget_parser.h b/src_mobile/configuration_parser/widget_parser.h new file mode 100644 index 0000000..f59b725 --- /dev/null +++ b/src_mobile/configuration_parser/widget_parser.h @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * This file have been implemented in compliance with W3C WARP SPEC. + * but there are some patent issue between W3C WARP SPEC and APPLE. + * so if you want to use this file, refer to the README file in root directory + */ +/** + * @file widget_parser.h + * @author Lukasz Wrzosek (l.wrzosek@samsung.com) + * @version 0.1 + * @brief + */ +#ifndef WIDGET_PARSER_H_ +#define WIDGET_PARSER_H_ + +#include "element_parser.h" +#include +#include +#include +#include + +namespace ConfigurationNamespace { +static const DPL::String W3CWidgetNamespaceName = + L"http://www.w3.org/ns/widgets"; +static const DPL::String TizenWebAppNamespaceName = + L"http://tizen.org/ns/widgets"; +} + +namespace PluginsPrefix { +const char * const W3CPluginsPrefix = "http://www.w3.org/"; +const char * const TIZENPluginsPrefix = "http://tizen.org/api/"; +} + +namespace Unicode { +enum Direction +{ + LRE, + RLE, + LRO, + RLO, + EMPTY +}; +} + +class WidgetParser : public ElementParser +{ + public: + ElementParserPtr OnNameElement(); + ElementParserPtr OnDescriptionElement(); + ElementParserPtr OnAuthorElement(); + ElementParserPtr OnLicenseElement(); + ElementParserPtr OnIconElement(); + ElementParserPtr OnContentElement(); + ElementParserPtr OnPreferenceElement(); + ElementParserPtr OnAccessElement(); + ElementParserPtr OnSettingElement(); + ElementParserPtr OnApplicationElement(); + ElementParserPtr OnSplashElement(); + ElementParserPtr OnBackgroundElement(); + ElementParserPtr OnPrivilegeElement(); + ElementParserPtr OnAppControlElement(); + ElementParserPtr OnCategoryElement(); + ElementParserPtr OnAppWidgetElement(); + ElementParserPtr OnCspElement(); + ElementParserPtr OnCspReportOnlyElement(); + ElementParserPtr OnAllowNavigationElement(); + ElementParserPtr OnAccountElement(); + ElementParserPtr OnMetadataElement(); + + virtual ActionFunc GetElementParser(const DPL::String& ns, + const DPL::String& name); + + virtual void Accept(const Element&); + virtual void Accept(const Text&); + virtual void Accept(const XmlAttribute&); + virtual void Verify(); + + //Typedef used by RootParser + typedef WrtDB::ConfigParserData& Data; + + WidgetParser(Data&); + + private: + Data& m_data; + Unicode::Direction m_textDirection; + FuncMap m_map; + DPL::Optional m_version; + DPL::Optional m_minVersion; + std::list m_windowModes; + DPL::Optional m_defaultlocale; + std::map m_nameSpaces; +}; + +struct IconParser; +struct ContentParser; + +#endif // WIDGET_PARSER_H_ diff --git a/src_mobile/jobs/job.cpp b/src_mobile/jobs/job.cpp new file mode 100644 index 0000000..ec2bb7f --- /dev/null +++ b/src_mobile/jobs/job.cpp @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include + +namespace Jobs { +Job::Job(InstallationType installType) : + m_handle(0), + m_installationType(installType), + m_abortStarted(false), + m_paused(false) +{} + +InstallationType Job::GetInstallationType() const +{ + return m_installationType; +} + +bool Job::GetAbortStarted() const +{ + return m_abortStarted; +} + +void Job::SetAbortStarted(bool flag) +{ + m_abortStarted = flag; +} + +bool Job::IsPaused() const +{ + return m_paused; +} + +void Job::SetPaused(bool paused) +{ + if (paused) { + Pause(); + } else { + Resume(); + } +} + +void Job::Pause() +{ + if (m_paused) { + return; + } + + // Pause + m_paused = true; +} + +void Job::Resume() +{ + if (!m_paused) { + return; + } + + // Continue + m_paused = false; + + // Trigger next steps + CONTROLLER_POST_EVENT(Logic::InstallerController, + InstallerControllerEvents::NextStepEvent(this)); +} + +void Job::SetJobHandle(JobHandle handle) +{ + m_handle = handle; +} + +JobHandle Job::GetJobHandle() const +{ + return m_handle; +} + +void Job::SendProgress() +{} + +void Job::SendFinishedSuccess() +{} + +void Job::SendFinishedFailure() +{} + +void Job::SendProgressIconPath(const std::string &/*path*/) +{} + +void Job::SaveExceptionData(const Jobs::JobExceptionBase&) +{} +} //namespace Jobs diff --git a/src_mobile/jobs/job.h b/src_mobile/jobs/job.h new file mode 100644 index 0000000..3963fc6 --- /dev/null +++ b/src_mobile/jobs/job.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef INSTALLER_MODEL_H +#define INSTALLER_MODEL_H + +#include + +#include + +namespace Jobs { +class JobExceptionBase; + +typedef int JobHandle; + +class Job : + public DPL::MutableTaskList +{ + public: + Job(InstallationType installType); + + InstallationType GetInstallationType() const; + + // Undo + void SetAbortStarted(bool flag); + bool GetAbortStarted() const; + + // Pause/resume support + bool IsPaused() const; + void SetPaused(bool paused); + void Pause(); + void Resume(); + void SetJobHandle(JobHandle handle); + JobHandle GetJobHandle() const; + virtual void SendProgress(); + virtual void SendFinishedSuccess(); + virtual void SendFinishedFailure(); + virtual void SendProgressIconPath(const std::string &path); + + virtual void SaveExceptionData(const Jobs::JobExceptionBase&); + + private: + JobHandle m_handle; + InstallationType m_installationType; + bool m_abortStarted; + bool m_paused; +}; +} //namespace Jobs + +#endif // INSTALLER_MODEL_H diff --git a/src_mobile/jobs/job_base.h b/src_mobile/jobs/job_base.h new file mode 100644 index 0000000..edcf0f5 --- /dev/null +++ b/src_mobile/jobs/job_base.h @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef SRC_INSTALLER_CORE_JOBS_JOB_BASE_H +#define SRC_INSTALLER_CORE_JOBS_JOB_BASE_H + +#include + +typedef std::string ProgressDescription; +typedef float ProgressPercent; + +namespace Jobs { +template +class JobProgressBase +{ + protected: + bool m_progressFlag; + ProgressDescription m_progresDescription; + ProgressPercent m_progresPercent; + + public: + JobProgressBase() : m_progressFlag(false), + m_progresPercent(0.0) + {} + + void SetProgressFlag(bool flag) + { + m_progressFlag = flag; + } + bool GetProgressFlag() const + { + return m_progressFlag; + } + + ProgressDescription GetProgressDescription() const + { + return m_progresDescription; + } + + ProgressPercent GetProgressPercent() const + { + return m_progresPercent; + } + + void UpdateProgress(T_InstallationStep step, + ProgressDescription const &description) + { + m_progresPercent = + ((static_cast(step)) / + static_cast(lastElement)) * 100; + m_progresDescription = description; + } +}; + +template +class JobContextBase +{ + public: + JobContextBase(const T_JobStruct& jobStruct) : + m_jobStruct(jobStruct) + {} + + T_JobStruct GetInstallerStruct() const + { + return m_jobStruct; + } + + protected: + T_JobStruct m_jobStruct; +}; + +template +struct JobCallbacksBase +{ + T_finishedCb finishedCallback; + T_progressCb progressCallback; + void *userParam; + + // It must be empty-constructible as a parameter of generic event + JobCallbacksBase() : + finishedCallback(0), + progressCallback(0), + userParam(0) + {} + + JobCallbacksBase(T_finishedCb finished, + T_progressCb progress, + void *param) : + finishedCallback(finished), + progressCallback(progress), + userParam(param) + {} +}; +} //namespace Jobs + +#endif // SRC_INSTALLER_CORE_JOBS_JOB_BASE_H diff --git a/src_mobile/jobs/job_exception_base.h b/src_mobile/jobs/job_exception_base.h new file mode 100644 index 0000000..4d35420 --- /dev/null +++ b/src_mobile/jobs/job_exception_base.h @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file job_exception_base.h + * @author Pawel Sikorski (p.sikorski@samgsung.com) + * @version + * @brief + */ + +#include + +#ifndef SRC_INSTALLER_CORE_JOBS_JOB_EXCEPTION_BASE_H_ +#define SRC_INSTALLER_CORE_JOBS_JOB_EXCEPTION_BASE_H_ + +#define DECLARE_JOB_EXCEPTION_BASE(Base, Class, Param) \ + class Class : \ + public Base { \ + public: \ + Class(const char *path, \ + const char *function, \ + int line, \ + const std::string & message = std::string()) : \ + Base(path, function, line, message) \ + { \ + m_className = #Class; \ + m_param = Param; \ + } \ + \ + Class(const char *path, \ + const char *function, \ + int line, \ + const Exception &reason, \ + const std::string & message = std::string()) : \ + Base(path, function, line, reason, message) \ + { \ + m_className = #Class; \ + m_param = Param; \ + } \ + \ + virtual int getParam() const \ + { \ + return m_param; \ + } \ + protected: \ + int m_param; \ + }; + +#define DECLARE_JOB_EXCEPTION(Base, Class, Param) \ + class Class : \ + public Base { \ + public: \ + Class(const char *path, \ + const char *function, \ + int line, \ + const std::string & message = std::string()) : \ + Base(path, function, line, message) \ + { \ + m_className = #Class; \ + m_param = Param; \ + } \ + \ + Class(const char *path, \ + const char *function, \ + int line, \ + const Exception &reason, \ + const std::string & message = std::string()) : \ + Base(path, function, line, reason, message) \ + { \ + m_className = #Class; \ + m_param = Param; \ + } \ + \ + virtual int getParam() const \ + { \ + return m_param; \ + } \ + }; + +namespace Jobs { +DECLARE_JOB_EXCEPTION_BASE(DPL::Exception, JobExceptionBase, 0) +} + +#endif /* SRC_INSTALLER_CORE_JOBS_JOB_EXCEPTION_BASE_H_ */ diff --git a/src_mobile/jobs/job_exception_error.h b/src_mobile/jobs/job_exception_error.h new file mode 100644 index 0000000..1caba99 --- /dev/null +++ b/src_mobile/jobs/job_exception_error.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file job_exception_error.h + * @author Soyoung Kim (sy037.kim@samsung.com) + * @version 1.0 + * @brief This file contains declarations of wrt api + */ + +/* + * @defgroup wrt_engine_group WebRunTime engine Library + * @ingroup internet_FW + * Functions to APIs to access wrt-engine + */ + +#ifndef JOB_EXCEPTION_ERROR_H +#define JOB_EXCEPTION_ERROR_H + +#include +#include + +namespace Jobs { +namespace Exceptions { +enum Type +{ + Success = 0, ///< Success + + /* pkgmgr error */ + ErrorPackageNotFound, ///< + ErrorPackageInvalid, ///< invalid widget package + ErrorPackageLowerVersion, ///< given version is lower + ErrorPackageExecutableNotFound, + + ErrorManifestNotFound = 11, ///< + ErrorManifestInvalid, ///< + ErrorConfigNotFound, ///< couldn't find config.xml + ErrorConfigInvalid, ///< invalid config.xml + + ErrorSignatureNotFound = 21, ///< signature file not exist. + ErrorSignatureInvalid, ///< invalid signature file + ErrorSignatureVerificationFailed, ///< failure in verificate + ///< signature + ErrorRootCertificateNotFound = 31, ///< couldn't find root + ErrorCertificationInvaid, ///< invalid certification + ErrorCertificateChainVerificationFailed, ///< failure in verificate + ErrorCertificateExpired, ///< expire cerification. + + ErrorInvalidPrivilege = 41, ///< invalid privilege. + ErrorPrivilegeLevelViolation, + + ErrorMenuIconNotFound = 51, ///< + + ErrorFatalError = 61, ///< failure in db operation + ErrorOutOfStorage, ///< failure in shortage of memory + ErrorOutOfMemory, ///< failure in shortage of RAM + ErrorArgumentInvalid, + + /* wrt-installer error */ + /* 121-140 : reserved for Web installer */ + ErrorPackageAlreadyInstalled = 121, ///< package already in target. + ErrorAceCheckFailed, ///< failure in ace check. + ErrorManifestCreateFailed, ///< failure in creating manifest + ErrorEncryptionFailed, ///< failure in encryption resource + ErrorInstallOspServcie, ///< Failure in installing osp service + ErrorPluginInstallationFailed, ///< failure in plugin installation + ErrorWidgetUninstallationFailed, ///< failure in uninstallation + ErrorNotSupportRDSUpdate, ///< failure in rds update + + ErrorUnknown = 140, ///< do not use this error code. +}; +} +} + +#endif /* JOB_EXCEPTION_ERROR_H */ diff --git a/src_mobile/jobs/job_types.h b/src_mobile/jobs/job_types.h new file mode 100644 index 0000000..5f845bf --- /dev/null +++ b/src_mobile/jobs/job_types.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file job_types.h + * @author Tomasz Iwanek () + */ +#ifndef JOB_TYPES_H +#define JOB_TYPES_H + +namespace Jobs { +/** + * @brief Defines installation and uninstallation type. + */ +enum InstallationType +{ + UnknownInstallation, ///< defines installation of yet unknown type + NewInstallation, ///< defines install process + UpdateInstallation, ///< defines update installation + Uninstallation, ///< defines uninstall process + PluginInstallation ///< defines plugin installation process +}; + +} + +#endif // JOB_TYPES_H diff --git a/src_mobile/jobs/plugin_install/job_plugin_install.cpp b/src_mobile/jobs/plugin_install/job_plugin_install.cpp new file mode 100644 index 0000000..2bcd9de --- /dev/null +++ b/src_mobile/jobs/plugin_install/job_plugin_install.cpp @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file job_plugin_install.cpp + * @author Pawel Sikorski (p.sikorski@samgsung.com) + * @version + * @brief + */ +#include +#include +#include "plugin_objects.h" +#include +#include + +namespace Jobs { +namespace PluginInstall { +JobPluginInstall::JobPluginInstall(PluginPath const &pluginPath, + const PluginInstallerStruct &installerStruct) + : + Job(PluginInstallation), + JobContextBase(installerStruct), + m_exceptionCaught(Jobs::Exceptions::Success) +{ + // + // Init installer context + // + m_context.pluginFilePath = pluginPath; + m_context.pluginHandle = INVALID_HANDLE; + m_context.installationCompleted = false; + + m_context.installerTask = this; + // + // Create main installation tasks + // + AddTask(new PluginInstallTask(&m_context)); +} + +void JobPluginInstall::SendProgress() +{ + if (GetProgressFlag() && GetInstallerStruct().progressCallback != NULL) { + _D("Call Plugin install progressCallback"); + GetInstallerStruct().progressCallback(GetInstallerStruct().userParam, + GetProgressPercent(), + GetProgressDescription()); + } +} + +void JobPluginInstall::SendFinishedSuccess() +{ + PluginHandle handle = getNewPluginHandle(); + + if (handle != Jobs::PluginInstall::JobPluginInstall::INVALID_HANDLE && + isReadyToInstall()) + { + _D("Call Plugin install success finishedCallback"); + GetInstallerStruct().finishedCallback(GetInstallerStruct().userParam, + Jobs::Exceptions::Success); + } else { + _D("Call Plugin install waiting finishedCallback"); + GetInstallerStruct().finishedCallback(GetInstallerStruct().userParam, + Jobs::Exceptions::ErrorPluginInstallationFailed); + + _D("Installation: %s NOT possible", getFilePath().c_str()); + } +} + +void JobPluginInstall::SendFinishedFailure() +{ + _E("Error in plugin installation step: %d", m_exceptionCaught); + _E("Message: %s", m_exceptionMessage.c_str()); + + _D("Call Plugin install failure finishedCallback"); + GetInstallerStruct().finishedCallback(GetInstallerStruct().userParam, + m_exceptionCaught); +} + +void JobPluginInstall::SaveExceptionData(const Jobs::JobExceptionBase &e) +{ + m_exceptionCaught = static_cast(e.getParam()); + m_exceptionMessage = e.GetMessage(); +} +} //namespace Jobs +} //namespace PluginInstall diff --git a/src_mobile/jobs/plugin_install/job_plugin_install.h b/src_mobile/jobs/plugin_install/job_plugin_install.h new file mode 100644 index 0000000..a8d3386 --- /dev/null +++ b/src_mobile/jobs/plugin_install/job_plugin_install.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file job_plugin_install.h + * @author Pawel Sikorski (p.sikorski@samgsung.com) + * @version + * @brief + */ + +#ifndef WRT_SRC_INSTALLER_CORE_JOB_JOB_PLUGIN_INSTALL_H_ +#define WRT_SRC_INSTALLER_CORE_JOB_JOB_PLUGIN_INSTALL_H_ + +//SYSTEM INCLUDES +#include + +//WRT INCLUDES +#include +#include +#include +#include +namespace Jobs { +namespace PluginInstall { +class JobPluginInstall : + public Job, + public JobProgressBase, + public JobContextBase +{ + public: + static const WrtDB::DbPluginHandle INVALID_HANDLE = -1; + + public: + /** + * @brief Automaticaly sets installation process + */ + JobPluginInstall(PluginPath const &pluginPath, + const PluginInstallerStruct &installerStruct); + + WrtDB::DbPluginHandle getNewPluginHandle() const + { + return m_context.pluginHandle; + } + std::string getFilePath() const + { + return m_context.pluginFilePath.Fullpath(); + } + bool isReadyToInstall() const + { + return m_context.installationCompleted; + } + + void SendProgress(); + void SendFinishedSuccess(); + void SendFinishedFailure(); + void SaveExceptionData(const Jobs::JobExceptionBase &e); + + private: + PluginInstallerContext m_context; + + //TODO move it to base class of all jobs + //maybe separate JobBase class for this? + Jobs::Exceptions::Type m_exceptionCaught; + std::string m_exceptionMessage; +}; +} //namespace Jobs +} //namespace PluginInstall + +#endif /* WRT_SRC_INSTALLER_CORE_JOB_JOB_PLUGIN_INSTALL_H_ */ diff --git a/src_mobile/jobs/plugin_install/plugin_install_task.cpp b/src_mobile/jobs/plugin_install/plugin_install_task.cpp new file mode 100644 index 0000000..5f42730 --- /dev/null +++ b/src_mobile/jobs/plugin_install/plugin_install_task.cpp @@ -0,0 +1,389 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file install_one_task.cpp + * @author Pawel Sikorski (p.sikorski@samgsung.com) + * @author Grzegorz Krawczyk (g.krawczyk@samgsung.com) + * @version + * @brief + */ + +//SYSTEM INCLUDES +#include +#include +#include + +//WRT INCLUDES +#include +#include +#include "plugin_install_task.h" +#include "job_plugin_install.h" +#include "plugin_installer_errors.h" +#include "plugin_metafile_reader.h" +#include +//#include +#include +#include +#include +#include "plugin_objects.h" +#include +#include +#include + +using namespace WrtDB; + +#define SET_PLUGIN_INSTALL_PROGRESS(step, desc) \ + m_context->installerTask->UpdateProgress( \ + PluginInstallerContext::step, desc); + +#define DISABLE_IF_PLUGIN_WITHOUT_LIB() \ + if (m_pluginInfo.m_libraryName.empty()) \ + { \ + _W("Plugin without library."); \ + return; \ + } + +namespace Jobs { +namespace PluginInstall { +PluginInstallTask::PluginInstallTask(PluginInstallerContext *inCont) : + DPL::TaskDecl(this), + m_context(inCont), + m_pluginHandle(0), + m_dataFromConfigXML(true) +{ + AddStep(&PluginInstallTask::stepCheckPluginPath); + AddStep(&PluginInstallTask::stepParseConfigFile); + AddStep(&PluginInstallTask::stepFindPluginLibrary); + AddStep(&PluginInstallTask::stepCheckIfAlreadyInstalled); + AddStep(&PluginInstallTask::stepLoadPluginLibrary); + AddStep(&PluginInstallTask::stepRegisterPlugin); + AddStep(&PluginInstallTask::stepRegisterFeatures); + AddStep(&PluginInstallTask::stepRegisterPluginObjects); + AddStep(&PluginInstallTask::stepResolvePluginDependencies); + + SET_PLUGIN_INSTALL_PROGRESS(START, "Installation initialized"); +} + +PluginInstallTask::~PluginInstallTask() +{} + +void PluginInstallTask::stepCheckPluginPath() +{ + _D("Plugin installation: step CheckPluginPath"); + + if(!m_context->pluginFilePath.Exists()){ + ThrowMsg(Exceptions::PluginPathFailed, + "No such path"); + } + + SET_PLUGIN_INSTALL_PROGRESS(PLUGIN_PATH, "Path to plugin verified"); +} + +void PluginInstallTask::stepParseConfigFile() +{ + _D("Plugin installation: step parse config file"); + + if(!m_context->pluginFilePath.getMetaFile().Exists()){ + m_dataFromConfigXML = false; + return; + } + + _D("Plugin Config file::%s", m_context->pluginFilePath.getMetaFile().Fullpath().c_str()); + + Try + { + PluginMetafileReader reader; + reader.initialize(m_context->pluginFilePath.getMetaFile()); + reader.read(m_pluginInfo); + + FOREACH(it, m_pluginInfo.m_featureContainer) + { + _D("Parsed feature : %s", it->m_name.c_str()); + FOREACH(devCap, it->m_deviceCapabilities) { + _D(" | DevCap : %s", (*devCap).c_str()); + } + } + + SET_PLUGIN_INSTALL_PROGRESS(PLUGIN_PATH, "Config file analyzed"); + } + Catch(ValidationCore::ParserSchemaException::Base) + { + _E("Error during file processing %s", m_context->pluginFilePath.getMetaFile().Fullpath().c_str()); + ThrowMsg(Exceptions::PluginMetafileFailed, + "Metafile error"); + } +} + +void PluginInstallTask::stepFindPluginLibrary() +{ + if (m_dataFromConfigXML) { + return; + } + _D("Plugin installation: step find plugin library"); + _D("Plugin .so: %s", m_context->pluginFilePath.getLibraryName().c_str()); + m_pluginInfo.m_libraryName = m_context->pluginFilePath.getLibraryName(); +} + +void PluginInstallTask::stepCheckIfAlreadyInstalled() +{ + if (PluginDAO::isPluginInstalled(m_pluginInfo.m_libraryName)) { + ThrowMsg(Exceptions::PluginAlreadyInstalled, + "Plugin already installed"); + } + + SET_PLUGIN_INSTALL_PROGRESS(PLUGIN_EXISTS_CHECK, "Check if plugin exist"); +} + +void PluginInstallTask::stepLoadPluginLibrary() +{ + _D("Plugin installation: step load library"); + + DISABLE_IF_PLUGIN_WITHOUT_LIB() + + _D("Loading plugin: %s", m_context->pluginFilePath.getLibraryName().c_str()); + + fprintf(stderr, " - Try to dlopen() : [%s] ", m_context->pluginFilePath.getLibraryPath().Fullpath().c_str()); + + void *dlHandle = dlopen( m_context->pluginFilePath.getLibraryPath().Fullpath().c_str(), RTLD_LAZY); + if (dlHandle == NULL) { + const char* error = (const char*)dlerror(); + fprintf(stderr, + "-> Failed!\n %s\n", + (error != NULL ? error : "unknown")); + _E("Failed to load plugin: %s. Reason: %s", + m_context->pluginFilePath.getLibraryName().c_str(), (error != NULL ? error : "unknown")); + ThrowMsg(Exceptions::PluginLibraryError, "Library error"); + } + + fprintf(stderr, "-> Done.\n"); + + const js_entity_definition_t *rawEntityList = NULL; + get_widget_entity_map_proc *getWidgetEntityMapProcPtr = NULL; + + getWidgetEntityMapProcPtr = + reinterpret_cast(dlsym(dlHandle, + PLUGIN_GET_CLASS_MAP_PROC_NAME)); + + if (getWidgetEntityMapProcPtr) { + rawEntityList = (*getWidgetEntityMapProcPtr)(); + } else { + rawEntityList = + static_cast(dlsym(dlHandle, + PLUGIN_CLASS_MAP_NAME)); + } + + if (rawEntityList == NULL) { + dlclose(dlHandle); + _E("Failed to read class name %s", m_context->pluginFilePath.getLibraryName().c_str()); + ThrowMsg(Exceptions::PluginLibraryError, "Library error"); + } + + if (!m_dataFromConfigXML) { + on_widget_init_proc *onWidgetInitProc = + reinterpret_cast( + dlsym(dlHandle, PLUGIN_WIDGET_INIT_PROC_NAME)); + + if (NULL == onWidgetInitProc) { + dlclose(dlHandle); + _E("Failed to read onWidgetInit symbol %s", m_context->pluginFilePath.getLibraryName().c_str()); + ThrowMsg(Exceptions::PluginLibraryError, "Library error"); + } + + // obtain feature -> dev-cap mapping + feature_mapping_interface_t mappingInterface = { NULL, NULL, NULL }; + (*onWidgetInitProc)(&mappingInterface); + + if (!mappingInterface.featGetter || !mappingInterface.release || + !mappingInterface.dcGetter) + { + _E("Failed to obtain mapping interface from .so"); + ThrowMsg(Exceptions::PluginLibraryError, "Library error"); + } + + feature_mapping_t* devcapMapping = mappingInterface.featGetter(); + + _D("Getting mapping from features to device capabilities"); + + for (size_t i = 0; i < devcapMapping->featuresCount; ++i) { + PluginMetafileData::Feature feature; + feature.m_name = devcapMapping->features[i].feature_name; + + _D("Feature: %s", feature.m_name.c_str()); + + const devcaps_t* dc = + mappingInterface.dcGetter( + devcapMapping, + devcapMapping->features[i]. + feature_name); + + if (dc) { + _D("devcaps count: %d", dc->devCapsCount); + + for (size_t j = 0; j < dc->devCapsCount; ++j) { + _D("devcap: %s", dc->deviceCaps[j]); + feature.m_deviceCapabilities.insert(dc->deviceCaps[j]); + } + } + + m_pluginInfo.m_featureContainer.insert(feature); + } + + mappingInterface.release(devcapMapping); + } + + m_libraryObjects = PluginObjectsPtr(new PluginObjects()); + const js_entity_definition_t *rawEntityListIterator = rawEntityList; + + _D("#####"); + _D("##### Plugin: %s supports new plugin API", + m_context->pluginFilePath.getLibraryName().c_str()); + _D("#####"); + + while (rawEntityListIterator->parent_name != NULL && + rawEntityListIterator->object_name != NULL) + { + _D("##### [%s]: ", rawEntityListIterator->object_name); + _D("##### Parent: %s", rawEntityListIterator->parent_name); + _D("#####"); + + m_libraryObjects->addObjects(rawEntityListIterator->parent_name, + rawEntityListIterator->object_name); + + ++rawEntityListIterator; + } + + // Unload library + if (dlclose(dlHandle) != 0) { + _E("Cannot close plugin handle"); + } else { + _D("Library is unloaded"); + } + + // Load export table + _D("Library successfuly loaded and parsed"); + + SET_PLUGIN_INSTALL_PROGRESS(LOADING_LIBRARY, "Library loaded and analyzed"); +} + +void PluginInstallTask::stepRegisterPlugin() +{ + _D("Plugin installation: step register Plugin"); + + m_pluginHandle = + PluginDAO::registerPlugin(m_pluginInfo, m_context->pluginFilePath.Fullpath()); + + SET_PLUGIN_INSTALL_PROGRESS(REGISTER_PLUGIN, "Plugin registered"); +} + +void PluginInstallTask::stepRegisterFeatures() +{ + _D("Plugin installation: step register features"); + + FOREACH(it, m_pluginInfo.m_featureContainer) + { + _D("PluginHandle: %d", m_pluginHandle); + FeatureDAO::RegisterFeature(*it, m_pluginHandle); + } + SET_PLUGIN_INSTALL_PROGRESS(REGISTER_FEATURES, "Features registered"); +} + +void PluginInstallTask::stepRegisterPluginObjects() +{ + _D("Plugin installation: step register objects"); + + DISABLE_IF_PLUGIN_WITHOUT_LIB() + + //register implemented objects + PluginObjects::ObjectsPtr objects = + m_libraryObjects->getImplementedObject(); + + FOREACH(it, *objects) + { + PluginDAO::registerPluginImplementedObject(*it, m_pluginHandle); + } + + //register requiredObjects + objects = m_libraryObjects->getDependentObjects(); + + FOREACH(it, *objects) + { + if (m_libraryObjects->hasObject(*it)) { + _D("Dependency from the same library. ignored"); + continue; + } + + PluginDAO::registerPluginRequiredObject(*it, m_pluginHandle); + } + + SET_PLUGIN_INSTALL_PROGRESS(REGISTER_OBJECTS, "Plugin Objects registered"); +} + +void PluginInstallTask::stepResolvePluginDependencies() +{ + _D("Plugin installation: step resolve dependencies "); + + //DISABLE_IF_PLUGIN_WITHOUT_LIB + if (m_pluginInfo.m_libraryName.empty()) { + PluginDAO::setPluginInstallationStatus( + m_pluginHandle, + PluginDAO:: + INSTALLATION_COMPLETED); + //Installation completed + m_context->pluginHandle = m_pluginHandle; + m_context->installationCompleted = true; + _W("Plugin without library."); + return; + } + + PluginHandleSetPtr handles = PluginHandleSetPtr(new PluginHandleSet); + + DbPluginHandle handle = INVALID_PLUGIN_HANDLE; + + //register requiredObjects + FOREACH(it, *(m_libraryObjects->getDependentObjects())) + { + if (m_libraryObjects->hasObject(*it)) { + _D("Dependency from the same library. ignored"); + continue; + } + + handle = PluginDAO::getPluginHandleForImplementedObject(*it); + if (handle == INVALID_PLUGIN_HANDLE) { + _E("Library implementing: %s NOT FOUND", (*it).c_str()); + PluginDAO::setPluginInstallationStatus( + m_pluginHandle, + PluginDAO::INSTALLATION_WAITING); + return; + } + + handles->insert(handle); + } + + PluginDAO::registerPluginLibrariesDependencies(m_pluginHandle, handles); + + PluginDAO::setPluginInstallationStatus(m_pluginHandle, + PluginDAO::INSTALLATION_COMPLETED); + + //Installation completed + m_context->pluginHandle = m_pluginHandle; + m_context->installationCompleted = true; + + SET_PLUGIN_INSTALL_PROGRESS(RESOLVE_DEPENDENCIES, "Dependencies resolved"); +} + +#undef SET_PLUGIN_INSTALL_PROGRESS +} //namespace Jobs +} //namespace PluginInstall diff --git a/src_mobile/jobs/plugin_install/plugin_install_task.h b/src_mobile/jobs/plugin_install/plugin_install_task.h new file mode 100644 index 0000000..c7a5d8c --- /dev/null +++ b/src_mobile/jobs/plugin_install/plugin_install_task.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file install.h + * @author Pawel Sikorski (p.sikorski@samgsung.com) + * @author Grzegorz Krawczyk (g.krawczyk@samgsung.com) + * @version + * @brief + */ + +#ifndef INSTALL_H_ +#define INSTALL_H_ + +//WRT INCLUDES +#include +#include "plugin_installer_context.h" +#include "plugin_objects.h" + +namespace Jobs { +namespace PluginInstall { +class PluginInstallTask : + public DPL::TaskDecl +{ + public: + PluginInstallTask(PluginInstallerContext *inCont); + virtual ~PluginInstallTask(); + + private: + //data + PluginInstallerContext *m_context; + + //PluginMetafile + WrtDB::PluginMetafileData m_pluginInfo; + + //Plugin LibraryObjects + PluginObjectsPtr m_libraryObjects; + + WrtDB::DbPluginHandle m_pluginHandle; + + bool m_dataFromConfigXML; + + //steps + void stepCheckPluginPath(); + void stepFindPluginLibrary(); + void stepParseConfigFile(); + void stepCheckIfAlreadyInstalled(); + void stepLoadPluginLibrary(); + void stepRegisterPlugin(); + void stepRegisterFeatures(); + void stepRegisterPluginObjects(); + void stepResolvePluginDependencies(); +}; +} //namespace Jobs +} //namespace PluginInstall + +#endif /* INSTALL_H_ */ diff --git a/src_mobile/jobs/plugin_install/plugin_installer_context.h b/src_mobile/jobs/plugin_install/plugin_installer_context.h new file mode 100644 index 0000000..1efd504 --- /dev/null +++ b/src_mobile/jobs/plugin_install/plugin_installer_context.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file plugin_installer_structs.h + * @author Pawel Sikorski (p.sikorski@samgsung.com) + * @version + * @brief Definition file of plugin installer tasks data structures + */ +#ifndef WRT_SRC_INSTALLERCORE_PLUGININSTALLERTASKS_PLUGININSTALLERCONTEXT_H_ +#define WRT_SRC_INSTALLERCORE_PLUGININSTALLERTASKS_PLUGININSTALLERCONTEXT_H_ + +#include +#include +#include +//#include + +using namespace WrtDB; + +namespace Jobs { +namespace PluginInstall { +class JobPluginInstall; +} +} + +struct PluginInstallerContext +{ + enum PluginInstallStep + { + START, + PLUGIN_PATH, + CONFIG_FILE, + PLUGIN_EXISTS_CHECK, + LOADING_LIBRARY, + REGISTER_PLUGIN, + REGISTER_FEATURES, + REGISTER_OBJECTS, + RESOLVE_DEPENDENCIES, + PLUGIN_INSTALL_END + }; + + PluginPath pluginFilePath; ///< plugin directory + PluginPath metaFilePath; + bool m_dataFromConfigXML; + WrtDB::DbPluginHandle pluginHandle; + // if this value is true the plugin model may be created + // if not plugin installation has failed from some reason + bool installationCompleted; + + //used to set installation progress + Jobs::PluginInstall::JobPluginInstall* installerTask; +}; +#endif // WRT_SRC_INSTALLERCORE_PLUGININSTALLERTASKS_PLUGININSTALLERCONTEXT_H_ diff --git a/src_mobile/jobs/plugin_install/plugin_installer_errors.h b/src_mobile/jobs/plugin_install/plugin_installer_errors.h new file mode 100644 index 0000000..11c7f88 --- /dev/null +++ b/src_mobile/jobs/plugin_install/plugin_installer_errors.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file plugin_installer_errors.h + * @author Pawel Sikorski (p.sikorski@samgsung.com) + * @author Grzegorz Krawczyk (g.krawczyk@samgsung.com) + * @version + * @brief + */ + +#ifndef \ + WRT_SRC_INSTALLER_CORE_PLUGIN_INSTALLER_TASKS_PLUGIN_INSTALLER_ERRORS_H_ +#define \ + WRT_SRC_INSTALLER_CORE_PLUGIN_INSTALLER_TASKS_PLUGIN_INSTALLER_ERRORS_H_ + +#include +#include + +using namespace Jobs::Exceptions; + +namespace Jobs { +namespace PluginInstall { +namespace Exceptions { + +DECLARE_JOB_EXCEPTION_BASE(JobExceptionBase, Base, ErrorUnknown) +DECLARE_JOB_EXCEPTION(Base, PluginPathFailed, ErrorPluginInstallationFailed) +DECLARE_JOB_EXCEPTION(Base, PluginMetafileFailed, ErrorPluginInstallationFailed) +DECLARE_JOB_EXCEPTION(Base, PluginAlreadyInstalled, + ErrorPluginInstallationFailed) +DECLARE_JOB_EXCEPTION(Base, PluginLibraryError, ErrorPluginInstallationFailed) +DECLARE_JOB_EXCEPTION(Base, InstallationWaitingError, + ErrorPluginInstallationFailed) +DECLARE_JOB_EXCEPTION(Base, UnknownError, ErrorUnknown) +} //namespace +} //namespace +} //namespace + +#endif +//WRT_SRC_INSTALLER_CORE_PLUGIN_INSTALLER_TASKS_PLUGIN_INSTALLER_ERRORS_H_ + diff --git a/src_mobile/jobs/plugin_install/plugin_installer_struct.h b/src_mobile/jobs/plugin_install/plugin_installer_struct.h new file mode 100644 index 0000000..c253897 --- /dev/null +++ b/src_mobile/jobs/plugin_install/plugin_installer_struct.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file plugin_installer_struct.h + * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com) + * @author Grzegorz Krawczyk (g.krawczyk@samsung.com) + * @version 1.0 + * @brief Implementation file for widget installer struct + */ +#ifndef WRT_SRC_INSTALLER_CORE_PLUGIN_INSTALLER_PLUGIN_INSTALLER_STRUCT_H_ +#define WRT_SRC_INSTALLER_CORE_PLUGIN_INSTALLER_PLUGIN_INSTALLER_STRUCT_H_ + +#include +#include + +//Plugin Installer typedefs +typedef void (*PluginInstallerFinishedCallback)( + void *userParam, + Jobs::Exceptions::Type); + +//installer progress +typedef void (*PluginInstallerProgressCallback)( + void *userParam, + ProgressPercent percent, + const ProgressDescription &description); + +//Plugin Installetion Struct +typedef Jobs::JobCallbacksBase +PluginInstallerStruct; + +#endif // WRT_SRC_INSTALLER_CORE_PLUGIN_INSTALLER_PLUGIN_INSTALLER_STRUCT_H_ diff --git a/src_mobile/jobs/plugin_install/plugin_metafile_reader.cpp b/src_mobile/jobs/plugin_install/plugin_metafile_reader.cpp new file mode 100644 index 0000000..c7df516 --- /dev/null +++ b/src_mobile/jobs/plugin_install/plugin_metafile_reader.cpp @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file plugin_metafile_reader.cpp + * @author Grzegorz Krawczyk(g.krawczyk@samsung.com) + * @version 1.0 + * @brief + */ + +#include "plugin_metafile_reader.h" +#include + +using namespace WrtDB; + +namespace { +const std::string XML_NAMESPACE = ""; + +const std::string TOKEN_LIBRARY_NAME = "library-name"; +const std::string TOKEN_API_FEATURE = "api-feature"; +const std::string TOKEN_NAME = "name"; +const std::string TOKEN_DEVICECAPABILITY = "device-capability"; +} + +PluginMetafileReader::PluginMetafileReader() : m_parserSchema(this) +{ + m_parserSchema.addEndTagCallback( + TOKEN_LIBRARY_NAME, + XML_NAMESPACE, + &PluginMetafileReader::tokenEndLibraryName); + + m_parserSchema.addEndTagCallback( + TOKEN_API_FEATURE, + XML_NAMESPACE, + &PluginMetafileReader::tokenEndApiFeature); + + m_parserSchema.addEndTagCallback( + TOKEN_NAME, + XML_NAMESPACE, + &PluginMetafileReader::tokenEndName); + + m_parserSchema.addEndTagCallback( + TOKEN_DEVICECAPABILITY, + XML_NAMESPACE, + &PluginMetafileReader::tokenEndDeviceCapability); +} + +void PluginMetafileReader::initialize(const PluginPath &filename) +{ + m_parserSchema.initialize(filename.Fullpath(), + true, + ValidationCore::SaxReader::VALIDATION_DTD, + std::string()); +} + +void PluginMetafileReader::read(WrtDB::PluginMetafileData &data) +{ + m_parserSchema.read(data); +} + +void PluginMetafileReader::blankFunction(PluginMetafileData & /* data */) +{} + +void PluginMetafileReader::tokenEndLibraryName(PluginMetafileData &data) +{ + data.m_libraryName = m_parserSchema.getText(); +} + +void PluginMetafileReader::tokenEndApiFeature(PluginMetafileData &data) +{ + data.m_featureContainer.insert(m_feature); + m_feature.m_deviceCapabilities.clear(); +} + +void PluginMetafileReader::tokenEndName(PluginMetafileData & /* data */) +{ + m_feature.m_name = m_parserSchema.getText(); +} + +void PluginMetafileReader::tokenEndDeviceCapability(PluginMetafileData& /*data*/) +{ + m_feature.m_deviceCapabilities.insert(m_parserSchema.getText()); +} + diff --git a/src_mobile/jobs/plugin_install/plugin_metafile_reader.h b/src_mobile/jobs/plugin_install/plugin_metafile_reader.h new file mode 100644 index 0000000..a3a3068 --- /dev/null +++ b/src_mobile/jobs/plugin_install/plugin_metafile_reader.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file plugin_metafile_reader.h + * @author Grzegorz Krawczyk(g.krawczyk@samsung.com) + * @version 1.0 + * @brief + */ + +#ifndef WRT_SRC_INSTALLER_CORE_PLUGIN_INSTALLER_TASKS_PLUGIN_METAFILE_READER_H_ +#define WRT_SRC_INSTALLER_CORE_PLUGIN_INSTALLER_TASKS_PLUGIN_METAFILE_READER_H_ + +#include +#include + +class PluginPath; + +class PluginMetafileReader +{ + public: + PluginMetafileReader(); + + void initialize(const PluginPath &filename); + + void read(WrtDB::PluginMetafileData &data); + + private: + void blankFunction(WrtDB::PluginMetafileData &data); + + void tokenEndLibraryName(WrtDB::PluginMetafileData &data); + void tokenEndApiFeature(WrtDB::PluginMetafileData &data); + void tokenEndName(WrtDB::PluginMetafileData &data); + void tokenEndDeviceCapability(WrtDB::PluginMetafileData &data); + + WrtDB::PluginMetafileData::Feature m_feature; + + ValidationCore::ParserSchema m_parserSchema; +}; + +#endif diff --git a/src_mobile/jobs/plugin_install/plugin_objects.cpp b/src_mobile/jobs/plugin_install/plugin_objects.cpp new file mode 100644 index 0000000..9235f47 --- /dev/null +++ b/src_mobile/jobs/plugin_install/plugin_objects.cpp @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file plugin_objects.h + * @author Grzegorz Krawczyk (g.krawczyk@samgsung.com) + * @version + * @brief + */ +#include +#include +#include "plugin_objects.h" + +namespace { +const char* SEPARATOR = "."; +const std::string GLOBAL_OBJECT_NAME = "GLOBAL_OBJECT"; + +std::string normalizeName(const std::string& objectName) +{ + if (objectName.empty()) { + _E("Normalize name, name size is 0"); + return objectName; + } + + if (!objectName.compare(0, GLOBAL_OBJECT_NAME.size(), + GLOBAL_OBJECT_NAME)) + { + return objectName; + } + + //each object in storage has name started from $GLOBAL_OBJECT_NAME$ + return GLOBAL_OBJECT_NAME + std::string(SEPARATOR) + objectName; +} + +std::string normalizeName(const std::string& objectName, + const std::string& parentName) +{ + if (objectName.empty() || parentName.empty()) { + _E("Normalize name, name size or parent name size is 0"); + return std::string(); + } + + std::string normalizedName; + normalizedName = normalizeName(parentName) + + std::string(SEPARATOR) + objectName; + + return normalizedName; +} +} + +PluginObjects::PluginObjects() +{ + m_implemented = ObjectsPtr(new Objects()); + m_dependent = ObjectsPtr(new Objects()); +} + +PluginObjects::ObjectsPtr PluginObjects::getImplementedObject() const +{ + return m_implemented; +} + +PluginObjects::ObjectsPtr PluginObjects::getDependentObjects() const +{ + return m_dependent; +} + +void PluginObjects::addObjects(const std::string& parentName, + const std::string& name) +{ + addImplementedObject(normalizeName(name, parentName)); + addDependentObject(normalizeName(parentName)); +} + +void PluginObjects::addDependentObject(const std::string& value) +{ + if (!value.compare(GLOBAL_OBJECT_NAME)) { + //dont add dependency to GLOBAL_OBJECT + return; + } + m_dependent->insert(value); +} + +bool PluginObjects::hasObject(const std::string& name) const +{ + return m_implemented->find(name) != m_implemented->end(); +} + +void PluginObjects::addImplementedObject(const std::string& value) +{ + m_implemented->insert(value); +} diff --git a/src_mobile/jobs/plugin_install/plugin_objects.h b/src_mobile/jobs/plugin_install/plugin_objects.h new file mode 100644 index 0000000..0b27a14 --- /dev/null +++ b/src_mobile/jobs/plugin_install/plugin_objects.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file plugin_objects.h + * @author Grzegorz Krawczyk(g.krawczyk@samsung.com) + * @version 1.0 + * @brief + */ + +#ifndef WRT_SRC_INSTALLER_CORE_PLUGIN_INSTALLER_TASKS_PLUGIN_OBJECTS_H_ +#define WRT_SRC_INSTALLER_CORE_PLUGIN_INSTALLER_TASKS_PLUGIN_OBJECTS_H_ + +#include +#include +#include +#include + +#include +//TODO TO BE MOVED SOMEWHERE ELSE +// AS OTHER MODULES (LIKE DAO) USE IT + +class PluginObjects : public WrtDB::PluginObjectsDAO +{ + public: + explicit PluginObjects(); + + //getters for objects from library + ObjectsPtr getImplementedObject() const; + ObjectsPtr getDependentObjects() const; + + //add object declaration + void addObjects(const std::string& parentName, + const std::string& name); + + //check if library implemements object given as name + bool hasObject(const std::string& name) const; + + private: + void addImplementedObject(const std::string& value); + void addDependentObject(const std::string& value); +}; + +typedef std::shared_ptr PluginObjectsPtr; + +#endif diff --git a/src_mobile/jobs/widget_install/ace_registration.cpp b/src_mobile/jobs/widget_install/ace_registration.cpp new file mode 100644 index 0000000..6596d47 --- /dev/null +++ b/src_mobile/jobs/widget_install/ace_registration.cpp @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file ace_registration.cpp + * @author Andrzej Surdej (a.surdej@gmail.com) + * @version 1.0 + * @brief Translate structures to ace api - implementation file + */ + +#include +#include +#include + +#include + +namespace { +char* toAceString(const DPL::OptionalString& os) +{ + if (!os.IsNull()) { + return strdup(DPL::ToUTF8String(*os).c_str()); + } else { + return NULL; + } +} + +char* toAceString(const std::string& str) +{ + if (!str.empty()) { + return strdup(str.c_str()); + } else { + return NULL; + } +} +} //anonymous namespace + +namespace AceApi { +bool registerAceWidget(const WrtDB::DbWidgetHandle& widgetHandle, + const WrtDB::WidgetRegisterInfo& widgetConfig, + const WrtDB::WidgetCertificateDataList& certList) +{ + _D("Updating Ace database"); + struct widget_info wi; + + switch (widgetConfig.webAppType.appType) { + case WrtDB::APP_TYPE_TIZENWEBAPP: + wi.type = Tizen; + break; + default: + _E("Unknown application type"); + return false; + } + + wi.id = toAceString(widgetConfig.configInfo.widget_id); + wi.version = toAceString(widgetConfig.configInfo.version); + wi.author = toAceString(widgetConfig.configInfo.authorName); + wi.shareHerf = strdup(widgetConfig.shareHref.c_str()); + _D("Basic data converted. Certificates begin."); + + //one more element for NULL termination + _D("Found: %d certificates", certList.size()); + ace_certificate_data** certData = new ace_certificate_data * + [certList.size() + 1]; + certData[certList.size()] = NULL; // last element set to NULL + + int i = 0; + FOREACH(it, certList) + { + certData[i] = new ace_certificate_data; + switch (it->owner) { + case WrtDB::WidgetCertificateData::AUTHOR: + certData[i]->owner = AUTHOR; + break; + case WrtDB::WidgetCertificateData::DISTRIBUTOR: + certData[i]->owner = DISTRIBUTOR; + break; + default: + _D("Unknown owner type of cert"); + certData[i]->owner = UNKNOWN; + break; + } + switch (it->type) { + case WrtDB::WidgetCertificateData::ENDENTITY: + certData[i]->type = ENDENTITY; + break; + case WrtDB::WidgetCertificateData::ROOT: + certData[i]->type = ROOT; + break; + default: + _E("Unknown type of cert"); + certData[i]->type = ENDENTITY; + break; + } + certData[i]->chain_id = it->chainId; + + certData[i]->md5_fp = toAceString(it->strMD5Fingerprint); + certData[i]->sha1_fp = toAceString(it->strSHA1Fingerprint); + certData[i]->common_name = + toAceString(DPL::ToUTF8String(it->strCommonName)); + ++i; + } + + _D("Registerign widget in ace"); + ace_return_t retval = ace_register_widget( + static_cast(widgetHandle), &wi, certData); + + //clean up - WidgetInfo + free(wi.author); + free(wi.id); + free(wi.shareHerf); + free(wi.version); + + //free cert list + i = 0; + while (certData[i] != NULL) { + free(certData[i]->common_name); + free(certData[i]->md5_fp); + free(certData[i]->sha1_fp); + delete certData[i]; + ++i; + } + delete[] certData; + return retval == ACE_OK; +} +bool registerAceWidgetFromDB(const WrtDB::DbWidgetHandle& widgetHandle) +{ + using namespace WrtDB; + _D("Updating Ace database from Widget DB"); + struct widget_info wi; + DPL::OptionalString os; + WrtDB::WidgetCertificateDataList certList; + + Try { + WidgetDAOReadOnly dao(widgetHandle); + + WidgetType type = dao.getWidgetType(); + if (type == WrtDB::APP_TYPE_TIZENWEBAPP) { + wi.type = Tizen; + } else { + _E("Unknown application type"); + return false; + } + + wi.id = toAceString(dao.getGUID()); + wi.version = toAceString(dao.getVersion()); + wi.author = toAceString(dao.getAuthorName()); + wi.shareHerf = strdup(dao.getShareHref().c_str()); + _D("Basic data converted. Certificates begin."); + certList = dao.getCertificateDataList(); + } + Catch(WidgetDAOReadOnly::Exception::WidgetNotExist) { + _E("Widget does not exist"); + return false; + } + + //one more element for NULL termination + _D("Found: %d certificates", certList.size()); + ace_certificate_data** certData = new ace_certificate_data * + [certList.size() + 1]; + certData[certList.size()] = NULL; // last element set to NULL + + int i = 0; + FOREACH(it, certList) + { + certData[i] = new ace_certificate_data; + switch (it->owner) { + case WrtDB::WidgetCertificateData::AUTHOR: + certData[i]->owner = AUTHOR; + break; + case WrtDB::WidgetCertificateData::DISTRIBUTOR: + certData[i]->owner = DISTRIBUTOR; + break; + default: + _D("Unknown owner type of cert"); + certData[i]->owner = UNKNOWN; + break; + } + switch (it->type) { + case WrtDB::WidgetCertificateData::ENDENTITY: + certData[i]->type = ENDENTITY; + break; + case WrtDB::WidgetCertificateData::ROOT: + certData[i]->type = ROOT; + break; + default: + _E("Unknown type of cert"); + certData[i]->type = ENDENTITY; + break; + } + certData[i]->chain_id = it->chainId; + + certData[i]->md5_fp = toAceString(it->strMD5Fingerprint); + certData[i]->sha1_fp = toAceString(it->strSHA1Fingerprint); + certData[i]->common_name = + toAceString(DPL::ToUTF8String(it->strCommonName)); + ++i; + } + + _D("Registerign widget in ace"); + ace_return_t retval = ace_register_widget( + static_cast(widgetHandle), &wi, certData); + + //clean up - WidgetInfo + free(wi.author); + free(wi.id); + free(wi.shareHerf); + free(wi.version); + + //free cert list + i = 0; + while (certData[i] != NULL) { + free(certData[i]->common_name); + free(certData[i]->md5_fp); + free(certData[i]->sha1_fp); + delete certData[i]; + ++i; + } + delete[] certData; + return retval == ACE_OK; +} +} diff --git a/src_mobile/jobs/widget_install/ace_registration.h b/src_mobile/jobs/widget_install/ace_registration.h new file mode 100644 index 0000000..f98c3ce --- /dev/null +++ b/src_mobile/jobs/widget_install/ace_registration.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file ace_registration.h + * @author Andrzej Surdej (a.surdej@gmail.com) + * @version 1.0 + * @brief Translate structures to ace api - header file + */ +#ifndef WRT_SRC_INSTALLER_CORE_ACE_REGISTRATION_H_ +#define WRT_SRC_INSTALLER_CORE_ACE_REGISTRATION_H_ + +#include + +namespace AceApi { +bool registerAceWidget(const WrtDB::DbWidgetHandle& widgetHandle, + const WrtDB::WidgetRegisterInfo& widgetConfig, + const WrtDB::WidgetCertificateDataList& certList); +bool registerAceWidgetFromDB(const WrtDB::DbWidgetHandle& widgetHandle); +} + +#endif /* WRT_SRC_INSTALLER_CORE_ACE_REGISTRATION_H_ */ + diff --git a/src_mobile/jobs/widget_install/directory_api.cpp b/src_mobile/jobs/widget_install/directory_api.cpp new file mode 100644 index 0000000..dd8aa07 --- /dev/null +++ b/src_mobile/jobs/widget_install/directory_api.cpp @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file directory_api.cpp + * @author Soyoung Kim(sy037.kim@samsung.com) + * @version 1.0 + * @brief directory api - implementation file + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace DirectoryApi { +bool DirectoryCopy(std::string source, std::string dest) +{ + DIR* dir = opendir(source.c_str()); + if (NULL == dir) { + return false; + } + + struct dirent dEntry; + struct dirent *dEntryResult; + int return_code; + + do { + struct stat statInfo; + return_code = readdir_r(dir, &dEntry, &dEntryResult); + if (dEntryResult != NULL && return_code == 0) { + std::string fileName = dEntry.d_name; + std::string fullName = source + "/" + fileName; + + if (stat(fullName.c_str(), &statInfo) != 0) { + closedir(dir); + return false; + } + + if (S_ISDIR(statInfo.st_mode)) { + if (("." == fileName) || (".." == fileName)) { + continue; + } + std::string destFolder = dest + "/" + fileName; + WrtUtilMakeDir(destFolder); + + if (!DirectoryCopy(fullName, destFolder)) { + closedir(dir); + return false; + } + } + + std::string destFile = dest + "/" + fileName; + std::ifstream infile(fullName); + std::ofstream outfile(destFile); + outfile << infile.rdbuf(); + outfile.close(); + infile.close(); + + errno = 0; + if (-1 == TEMP_FAILURE_RETRY(chown(destFile.c_str(), + statInfo.st_uid, + statInfo.st_gid))) { + int error = errno; + _E("Failed to change owner [%s]", DPL::GetErrnoString(error).c_str()); + } + } + } while (dEntryResult != NULL && return_code == 0); + closedir(dir); + return true; +} +} diff --git a/src_mobile/jobs/widget_install/directory_api.h b/src_mobile/jobs/widget_install/directory_api.h new file mode 100644 index 0000000..1632528 --- /dev/null +++ b/src_mobile/jobs/widget_install/directory_api.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file directory_api.h + * @author Soyoung Kim(sy037.kim@samsung.com) + * @version 1.0 + * @brief directory api - header file + */ +#ifndef WRT_SRC_INSTALLER_CORE_DIRECTORY_API_H_ +#define WRT_SRC_INSTALLER_CORE_DIRECTORY_API_H_ + +#include + +namespace DirectoryApi { +bool DirectoryCopy(std::string source, std::string dest); +} + +#endif /* WRT_SRC_INSTALLER_CORE_DIRECTORY_API_H_ */ + diff --git a/src_mobile/jobs/widget_install/job_widget_install.cpp b/src_mobile/jobs/widget_install/job_widget_install.cpp new file mode 100644 index 0000000..58e2068 --- /dev/null +++ b/src_mobile/jobs/widget_install/job_widget_install.cpp @@ -0,0 +1,327 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file job_widget_install.cpp + * @author Radoslaw Wicik r.wicik@samsung.com + * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com) + * @version 1.0 + * @brief Implementation file for main installer task + */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include "root_parser.h" +#include "widget_parser.h" +#include "parser_runner.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +using namespace WrtDB; +using namespace Jobs::Exceptions; + +namespace Jobs { +namespace WidgetInstall { + +JobWidgetInstall::JobWidgetInstall( + std::string const &widgetPath, + std::string const &tzPkgId, + const Jobs::WidgetInstall::WidgetInstallationStruct & + installerStruct) : + Job(UnknownInstallation), + JobContextBase(installerStruct), + m_exceptionCaught(Jobs::Exceptions::Success) +{ + m_installerContext.mode = m_jobStruct.m_installMode; + m_installerContext.requestedPath = widgetPath; + m_jobStruct.pkgmgrInterface->setPkgname(tzPkgId); + + //start configuration of installation + AddTask(new TaskConfiguration(m_installerContext)); + + // Init installer context + m_installerContext.installStep = InstallerContext::INSTALL_START; + m_installerContext.job = this; + + m_installerContext.callerPkgId + = DPL::FromUTF8String(m_jobStruct.pkgmgrInterface->getCallerId()); + _D("Caller Package Id : %s", DPL::ToUTF8String(m_installerContext.callerPkgId).c_str()); +} + +void JobWidgetInstall::appendNewInstallationTaskList() +{ + _D("Configure installation succeeded"); + m_installerContext.job->SetProgressFlag(true); + + AddTask(new TaskRecovery(m_installerContext)); + + AddTask(new TaskFileManipulation(m_installerContext)); + AddTask(new TaskProcessConfig(m_installerContext)); + if (m_installerContext.widgetConfig.packagingType == + WrtDB::PKG_TYPE_HOSTED_WEB_APP) + { + AddTask(new TaskPrepareFiles(m_installerContext)); + } + AddTask(new TaskCertify(m_installerContext)); + AddTask(new TaskCertifyLevel(m_installerContext)); + AddTask(new TaskUserDataManipulation(m_installerContext)); + if (m_installerContext.needEncryption) { + AddTask(new TaskEncryptResource(m_installerContext)); + } + AddTask(new TaskManifestFile(m_installerContext)); + if (m_installerContext.widgetConfig.packagingType == + PKG_TYPE_HYBRID_WEB_APP) + { + AddTask(new TaskInstallOspsvc(m_installerContext)); + } + AddTask(new TaskDatabase(m_installerContext)); + AddTask(new TaskAceCheck(m_installerContext)); + AddTask(new TaskSmack(m_installerContext)); + AddTask(new TaskPkgInfoUpdate(m_installerContext)); +} + +void JobWidgetInstall::appendUpdateInstallationTaskList() +{ + _D("Configure installation updated"); + _D("Widget Update"); + m_installerContext.job->SetProgressFlag(true); + + if (m_installerContext.mode.command == + InstallMode::Command::REINSTALL) + { + AddTask(new TaskPrepareReinstall(m_installerContext)); + } + + if (m_installerContext.mode.extension != + InstallMode::ExtensionType::DIR) { + AddTask(new TaskUpdateFiles(m_installerContext)); + AddTask(new TaskFileManipulation(m_installerContext)); + } + + AddTask(new TaskProcessConfig(m_installerContext)); + + if (m_installerContext.widgetConfig.packagingType == + WrtDB::PKG_TYPE_HOSTED_WEB_APP) + { + AddTask(new TaskPrepareFiles(m_installerContext)); + } + + AddTask(new TaskCertify(m_installerContext)); + AddTask(new TaskCertifyLevel(m_installerContext)); + AddTask(new TaskUserDataManipulation(m_installerContext)); + if (m_installerContext.needEncryption) { + AddTask(new TaskEncryptResource(m_installerContext)); + } + + AddTask(new TaskManifestFile(m_installerContext)); + if (m_installerContext.widgetConfig.packagingType == + PKG_TYPE_HYBRID_WEB_APP) + { + AddTask(new TaskInstallOspsvc(m_installerContext)); + } + + AddTask(new TaskDatabase(m_installerContext)); + AddTask(new TaskAceCheck(m_installerContext)); + //TODO: remove widgetHandle from this task and move before database task + // by now widget handle is needed in ace check + // Any error in acecheck while update will break widget + AddTask(new TaskSmack(m_installerContext)); + AddTask(new TaskRemoveBackupFiles(m_installerContext)); + AddTask(new TaskPkgInfoUpdate(m_installerContext)); +} + +void JobWidgetInstall::SendProgress() +{ + using namespace PackageManager; + if (GetProgressFlag() != false) { + if (GetInstallerStruct().progressCallback != NULL) { + // send progress signal of pkgmgr + GetInstallerStruct().pkgmgrInterface->sendProgress(GetProgressPercent()); + + _D("Call widget install progressCallback"); + GetInstallerStruct().progressCallback( + GetInstallerStruct().userParam, + GetProgressPercent(), + GetProgressDescription()); + } + } +} + +void JobWidgetInstall::SendProgressIconPath(const std::string &path) +{ + using namespace PackageManager; + if (GetProgressFlag() != false) { + if (GetInstallerStruct().progressCallback != NULL) { + // send progress signal of pkgmgr + GetInstallerStruct().pkgmgrInterface->sendIconPath(path); + } + } +} + +void JobWidgetInstall::SendFinishedSuccess() +{ + using namespace PackageManager; + // TODO : sync should move to separate task. + sync(); + + if (INSTALL_LOCATION_TYPE_PREFER_EXTERNAL == m_installerContext.locationType) { + if (m_installerContext.isUpdateMode) { + WidgetInstallToExtSingleton::Instance().postUpgrade(true); + } else { + WidgetInstallToExtSingleton::Instance().postInstallation(true); + } + WidgetInstallToExtSingleton::Instance().deinitialize(); + } + + // remove widget install information file + unlink(m_installerContext.installInfo.c_str()); + + //inform widget info + JobWidgetInstall::displayWidgetInfo(); + + TizenAppId& tizenId = m_installerContext.widgetConfig.tzAppid; + + // send signal of pkgmgr + GetInstallerStruct().pkgmgrInterface->endJob(m_exceptionCaught); + + _D("Call widget install successfinishedCallback"); + GetInstallerStruct().finishedCallback(GetInstallerStruct().userParam, + DPL::ToUTF8String( + tizenId), Jobs::Exceptions::Success); +} + +void JobWidgetInstall::SendFinishedFailure() +{ + using namespace PackageManager; + // remove widget install information file + unlink(m_installerContext.installInfo.c_str()); + + _E("Error number: %d", m_exceptionCaught); + _E("Message: %s", m_exceptionMessage.c_str()); + TizenAppId & tizenId = m_installerContext.widgetConfig.tzAppid; + + _D("Call widget install failure finishedCallback"); + + // send signal of pkgmgr + GetInstallerStruct().pkgmgrInterface->endJob(m_exceptionCaught); + + GetInstallerStruct().finishedCallback(GetInstallerStruct().userParam, + DPL::ToUTF8String( + tizenId), m_exceptionCaught); +} + +void JobWidgetInstall::SaveExceptionData(const Jobs::JobExceptionBase &e) +{ + m_exceptionCaught = static_cast(e.getParam()); + m_exceptionMessage = e.GetMessage(); +} + +void JobWidgetInstall::displayWidgetInfo() +{ + WidgetDAOReadOnly dao(m_installerContext.widgetConfig.tzAppid); + + std::ostringstream out; + WidgetLocalizedInfo localizedInfo = + W3CFileLocalization::getLocalizedInfo(dao.getTzAppId()); + + out << std::endl << + "===================================== INSTALLED WIDGET INFO =========" \ + "============================"; + out << std::endl << "Name: " << localizedInfo.name; + out << std::endl << "AppId: " << dao.getTzAppId(); + WidgetSize size = dao.getPreferredSize(); + out << std::endl << "Width: " << size.width; + out << std::endl << "Height: " << size.height; + out << std::endl << "Start File: " << + W3CFileLocalization::getStartFile(dao.getTzAppId()); + out << std::endl << "Version: " << dao.getVersion(); + out << std::endl << "Licence: " << + localizedInfo.license; + out << std::endl << "Licence Href: " << + localizedInfo.licenseHref; + out << std::endl << "Description: " << + localizedInfo.description; + out << std::endl << "Widget Id: " << dao.getGUID(); + out << std::endl << "Widget recognized: " << dao.isRecognized(); + out << std::endl << "Widget distributor signed: " << + dao.isDistributorSigned(); + out << std::endl << "Widget trusted: " << dao.isTrusted(); + + OptionalWidgetIcon icon = W3CFileLocalization::getIcon(dao.getTzAppId()); + DPL::OptionalString iconSrc = + !!icon ? icon->src : DPL::OptionalString::Null; + out << std::endl << "Icon: " << iconSrc; + + out << std::endl << "Preferences:"; + { + PropertyDAOReadOnly::WidgetPreferenceList list = dao.getPropertyList(); + FOREACH(it, list) + { + out << std::endl << " Key: " << + it->key_name; + out << std::endl << " Readonly: " << + it->readonly; + } + } + + out << std::endl << "Features:"; + { + WidgetFeatureSet list = dao.getFeaturesList(); + FOREACH(it, list) + { + out << std::endl << " Name: " << it->name; + } + } + + out << std::endl; + + _D("%s", out.str().c_str()); +} +} //namespace WidgetInstall +} //namespace Jobs diff --git a/src_mobile/jobs/widget_install/job_widget_install.h b/src_mobile/jobs/widget_install/job_widget_install.h new file mode 100644 index 0000000..a87337d --- /dev/null +++ b/src_mobile/jobs/widget_install/job_widget_install.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file job_widget_install.h + * @author Radoslaw Wicik r.wicik@samsung.com + * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com) + * @version 1.0 + * @brief Implementation file for main installer task + */ +#ifndef WRT_SRC_INSTALLER_CORE_JOB_JOB_WIDGET_INSTALL_H_ +#define WRT_SRC_INSTALLER_CORE_JOB_JOB_WIDGET_INSTALL_H_ + +#include +#include +#include +#include "widget_installer_struct.h" +#include + +using namespace Jobs::Exceptions; + +namespace Jobs { +namespace WidgetInstall { + +typedef JobProgressBase InstallerBase; +typedef JobContextBase WidgetInstallationBase; + +class JobWidgetInstall : + public Job, + public InstallerBase, + public WidgetInstallationBase + +{ + private: + InstallerContext m_installerContext; + + Jobs::Exceptions::Type m_exceptionCaught; + std::string m_exceptionMessage; + + public: + /** + * @brief Automaticaly sets installation process + */ + JobWidgetInstall(std::string const & widgetPath, + std::string const &tzPkgId, + const Jobs::WidgetInstall::WidgetInstallationStruct &installerStruct); + + //overrides + void SendProgress(); + void SendFinishedSuccess(); + void SendFinishedFailure(); + void SendProgressIconPath(const std::string &path); + + void SaveExceptionData(const Jobs::JobExceptionBase&); + void displayWidgetInfo(); + + //execution paths + void appendNewInstallationTaskList(); + void appendUpdateInstallationTaskList(); +}; +} //namespace WidgetInstall +} //namespace Jobs + +#endif // WRT_SRC_INSTALLER_CORE_JOB_JOB_WIDGET_INSTALL_H_ diff --git a/src_mobile/jobs/widget_install/languages.def b/src_mobile/jobs/widget_install/languages.def new file mode 100644 index 0000000..e9439b6 --- /dev/null +++ b/src_mobile/jobs/widget_install/languages.def @@ -0,0 +1,15 @@ +ADD(de, de-de) +ADD(el, el-gr) +ADD(en, en-us) +ADD(es, es-es) +ADD(fr, fr-fr) +ADD(it, it-it) +ADD(ja, ja-jp) +ADD(ko, ko-kr) +ADD(nl, nl-nl) +ADD(pt, pt-pt) +ADD(ru, ru-ru) +ADD(tr, tr-tr) +ADD(zh, zh-cn) +ADD(zh, zh-hk) +ADD(zh, zh-tw) diff --git a/src_mobile/jobs/widget_install/manifest.cpp b/src_mobile/jobs/widget_install/manifest.cpp new file mode 100644 index 0000000..1e02cfa --- /dev/null +++ b/src_mobile/jobs/widget_install/manifest.cpp @@ -0,0 +1,526 @@ +/* + * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file manifest.cpp + * @author Mariusz Domanski (m.domanski@samsung.com) + */ + +#include "manifest.h" +#include "libxml_utils.h" +#include +#include +#include + +namespace Jobs { +namespace WidgetInstall { +void writeElement(xmlTextWriterPtr writer, const char * name, DPL::String body) +{ + int state = xmlTextWriterWriteElement(writer, BAD_CAST name, + BAD_CAST DPL::ToUTF8String( + body).c_str()); + if (state < 0) { + ThrowMsg(LibxmlUtils::Libxml2Error, "xmlTextWriterWriteElement failed"); + } +} + +void writeText(xmlTextWriterPtr writer, DPL::String text) +{ + int state = xmlTextWriterWriteString(writer, + BAD_CAST DPL::ToUTF8String(text).c_str()); + if (state < 0) { + ThrowMsg(LibxmlUtils::Libxml2Error, "xmlTextWriterWriteText failed"); + } +} + +void writeElement(xmlTextWriterPtr writer, const char * name, const char * body) +{ + int state = xmlTextWriterWriteElement(writer, BAD_CAST name, BAD_CAST body); + if (state < 0) { + ThrowMsg(LibxmlUtils::Libxml2Error, "xmlTextWriterWriteElement failed"); + } +} + +void writeElementWithOneAttribute(xmlTextWriterPtr writer, + const char * name, + DPL::String body, + const char * nameAttr, + DPL::String bodyAttr, + bool condition = true) +{ + startElement(writer, name); + writeAttribute(writer, nameAttr, bodyAttr, condition); + writeText(writer, body); + endElement(writer); +} + +void startElement(xmlTextWriterPtr writer, const char * name) +{ + int state = xmlTextWriterStartElement(writer, BAD_CAST name); + if (state < 0) { + ThrowMsg(LibxmlUtils::Libxml2Error, "xmlTextWriterStartElement failed"); + } +} + +void endElement(xmlTextWriterPtr writer) +{ + int state = xmlTextWriterEndElement(writer); + if (state < 0) { + ThrowMsg(LibxmlUtils::Libxml2Error, "xmlTextWriterEndElement failed"); + } +} + +void writeAttribute(xmlTextWriterPtr writer, + const char * name, + DPL::String body, + bool condition = true) +{ + if (!condition) { + return; + } + int state = xmlTextWriterWriteAttribute(writer, BAD_CAST name, + BAD_CAST DPL::ToUTF8String( + body).c_str()); + if (state < 0) { + ThrowMsg(LibxmlUtils::Libxml2Error, + "xmlTextWriterWriteAttribute failed"); + } +} + +void writeAttribute(xmlTextWriterPtr writer, + const char * name, + const char * body, + bool condition = true) +{ + if (!condition) { + return; + } + int state = xmlTextWriterWriteAttribute(writer, + BAD_CAST name, + BAD_CAST body); + if (state < 0) { + ThrowMsg(LibxmlUtils::Libxml2Error, + "xmlTextWriterWriteAttribute failed"); + } +} + +void Manifest::generate(DPL::String filename) +{ + xmlTextWriterPtr writer; + int state; + + //compression set to 0 + writer = xmlNewTextWriterFilename(DPL::ToUTF8String(filename).c_str(), 0); + + if (writer == NULL) { + ThrowMsg(LibxmlUtils::Libxml2Error, "xmlNewTextWriterFilename failed"); + } + state = xmlTextWriterSetIndent(writer, 1); + if (state < 0) { + ThrowMsg(LibxmlUtils::Libxml2Error, "xmlTextWriterSetIndent failed"); + } + + state = xmlTextWriterStartDocument(writer, NULL, "utf-8", NULL); + if (state < 0) { + ThrowMsg(LibxmlUtils::Libxml2Error, "xmlTextWriterStartDocument failed"); + } + this->serialize(writer); + state = xmlTextWriterEndDocument(writer); + if (state < 0) { + ThrowMsg(LibxmlUtils::Libxml2Error, "xmlTextWriterEndDocument failed"); + } + if (writer != NULL) { + xmlFreeTextWriter(writer); + writer = NULL; + } +} + +void Manifest::serialize(xmlTextWriterPtr writer) +{ + startElement(writer, "manifest"); + { + writeAttribute(writer, "xmlns", "http://tizen.org/ns/packages"); + writeAttribute(writer, "package", this->package); + writeAttribute(writer, "type", this->type); + writeAttribute(writer, "version", this->version); + if (!this->installLocation.IsNull()) { + writeAttribute(writer, "install-location", (*this->installLocation)); + } + writeAttribute(writer, "storeclient-id", this->storeClientId, + !this->storeClientId.empty()); + + FOREACH(l, this->label) + { + writeElementWithOneAttribute(writer, "label", l->getString(), + "xml:lang", l->getLang(), l->hasLang()); + } + FOREACH(i, this->icon) + { + writeElementWithOneAttribute(writer, "icon", i->getString(), + "xml:lang", i->getLang(), i->hasLang()); + } + FOREACH(a, this->author) + { + a->serialize(writer); + } + FOREACH(d, this->description) + { + writeElementWithOneAttribute(writer, "description", d->getString(), + "xml:lang", d->getLang(), d->hasLang()); + } + //FOREACH(c, this->compatibility) { c->serialize(writer); } + //FOREACH(d, this->deviceProfile) { d->serialize(writer); } + FOREACH(s, this->serviceApplication) { + s->serialize(writer); + } + FOREACH(u, this->uiApplication) { + u->serialize(writer); + } + FOREACH(i, this->imeApplication) { + i->serialize(writer); + } + //FOREACH(f, this->font) { f->serialize(writer); } + FOREACH(l, this->livebox) { + l->serialize(writer); + } + FOREACH(acc, this->account) + { + acc->serialize(writer); + } + + if (!this->privileges.isEmpty()) { + this->privileges.serialize(writer); + } + } + endElement(writer); +} + +void Author::serialize(xmlTextWriterPtr writer) +{ + startElement(writer, "author"); + writeAttribute(writer, "email", this->email, !this->email.empty()); + writeAttribute(writer, "href", this->href, !this->href.empty()); + writeAttribute(writer, "xml:lang", this->lang, !this->lang.empty()); + writeText(writer, body); + endElement(writer); +} + +void ServiceApplication::serialize(xmlTextWriterPtr writer) +{ + startElement(writer, "service-application"); + writeAttribute(writer, "appid", this->appid); + writeAttribute(writer, "auto-restart", + (!this->autoRestart.IsNull() && + (*this->autoRestart)) ? "true" : + "false"); + writeAttribute(writer, "exec", this->exec); + writeAttribute(writer, "on-boot", (!this->onBoot.IsNull() && + (*this->onBoot)) ? "true" : "false"); + writeAttribute(writer, "type", this->type); + FOREACH(l, this->label) + { + writeElementWithOneAttribute(writer, "label", + l->getString(), "xml:lang", + l->getLang(), l->hasLang()); + } + FOREACH(i, this->icon) + { + writeElementWithOneAttribute(writer, "icon", i->getString(), "xml:lang", + i->getLang(), i->hasLang()); + } + FOREACH(a, this->appControl) + { + a->serialize(writer); + } + endElement(writer); +} + +void UiApplication::serialize(xmlTextWriterPtr writer) +{ + startElement(writer, "ui-application"); + writeAttribute(writer, "appid", this->appid); + writeAttribute(writer, "exec", this->exec); + if (!this->multiple.IsNull()) { + writeAttribute(writer, "multiple", (*this->multiple) ? "true" : "false"); + } + if (!this->nodisplay.IsNull()) { + writeAttribute(writer, + "nodisplay", + (*this->nodisplay) ? "true" : "false"); + } + if (!this->taskmanage.IsNull()) { + writeAttribute(writer, + "taskmanage", + (*this->taskmanage) ? "true" : "false"); + } + writeAttribute(writer, "type", this->type); + writeAttribute(writer, "extraid", this->extraid); + if (!this->categories.IsNull()) { + writeAttribute(writer, "categories", (*this->categories)); + } + FOREACH(l, this->label) + { + writeElementWithOneAttribute(writer, "label", + l->getString(), "xml:lang", + l->getLang(), l->hasLang()); + } + FOREACH(i, this->icon) + { + writeElementWithOneAttribute(writer, "icon", i->getString(), "xml:lang", + i->getLang(), i->hasLang()); + } + FOREACH(a, this->appControl) + { + a->serialize(writer); + } + FOREACH(c, this->appCategory) + { + startElement(writer, "category"); + writeAttribute(writer, "name", *c); + endElement(writer); + } + FOREACH(m, this->metadata) { + m->serialize(writer); + } + endElement(writer); +} + +void ImeApplication::serialize(xmlTextWriterPtr writer) +{ + startElement(writer, "ime-application"); + writeAttribute(writer, "appid", this->appid); + writeAttribute(writer, "exec", this->exec); + if (!this->multiple.IsNull()) { + writeAttribute(writer, "multiple", (*this->multiple) ? "true" : "false"); + } + if (!this->nodisplay.IsNull()) { + writeAttribute(writer, + "nodisplay", + (*this->nodisplay) ? "true" : "false"); + } + writeAttribute(writer, "type", this->type); + FOREACH(l, this->label) + { + writeElementWithOneAttribute(writer, "label", + l->getString(), "xml:lang", + l->getLang(), l->hasLang()); + } + FOREACH(i, this->icon) + { + writeElementWithOneAttribute(writer, "icon", i->getString(), "xml:lang", + i->getLang(), i->hasLang()); + } + endElement(writer); +} + +void AppControl::serialize(xmlTextWriterPtr writer) +{ + startElement(writer, "app-control"); + FOREACH(o, this->operation) + { + startElement(writer, "operation"); + writeAttribute(writer, "name", *o); + endElement(writer); + } + FOREACH(u, this->uri) + { + startElement(writer, "uri"); + writeAttribute(writer, "name", *u); + endElement(writer); + } + FOREACH(m, this->mime) + { + startElement(writer, "mime"); + writeAttribute(writer, "name", *m); + endElement(writer); + } + endElement(writer); +} + +void LiveBox::serialize(xmlTextWriterPtr writer) +{ + startElement(writer, "livebox"); + if (!this->liveboxId.empty()) { + writeAttribute(writer, "appid", this->liveboxId); + } + + if (!this->primary.empty()) { + writeAttribute(writer, "primary", this->primary); + } + + if (!this->updatePeriod.empty()) { + writeAttribute(writer, "period", this->updatePeriod); + } + + writeAttribute(writer, "abi", "html"); + writeAttribute(writer, "network", "true"); + writeAttribute(writer, "nodisplay", "false"); + + if (!this->label.empty()) { + int defaultLabelChk = 0; + FOREACH(m, this->label) + { + std::pair boxLabel = *m; + startElement(writer, "label"); + if (!boxLabel.first.empty()) { + writeAttribute(writer, "xml:lang", boxLabel.first); + } else { + defaultLabelChk++; + } + writeText(writer, boxLabel.second); + endElement(writer); + } + if(!defaultLabelChk) { + startElement(writer, "label"); + writeText(writer, DPL::FromUTF8String("NO NAME")); + endElement(writer); + } + } + if (!this->icon.empty()) { + startElement(writer, "icon"); + writeText(writer, this->icon); + endElement(writer); + } + + if (!this->autoLaunch.empty()) { + startElement(writer, "launch"); + writeText(writer, this->autoLaunch); + endElement(writer); + } + + if (!this->box.boxSrc.empty() && + !this->box.boxMouseEvent.empty() && + !this->box.boxSize.empty()) + { + startElement(writer, "box"); + writeAttribute(writer, "type", "buffer"); + writeAttribute(writer, "mouse_event", this->box.boxMouseEvent); + writeAttribute(writer, "touch_effect", this->box.boxTouchEffect); + + FOREACH(it, this->box.boxSize) + { + startElement(writer, "size"); + if (!(*it).m_preview.empty()) { + writeAttribute(writer, "preview", (*it).m_preview); + } + if (!(*it).m_useDecoration.empty()) { + writeAttribute(writer, "need_frame", (*it).m_useDecoration); + } else { + // default value of use-decoration is "true" + writeAttribute(writer, "need_frame", DPL::String(L"true")); + } + + writeText(writer, (*it).m_size); + endElement(writer); + } + + startElement(writer, "script"); + writeAttribute(writer, "src", this->box.boxSrc); + endElement(writer); + + endElement(writer); + + if (!this->box.pdSrc.empty() && + !this->box.pdWidth.empty() && + !this->box.pdHeight.empty()) + { + startElement(writer, "pd"); + writeAttribute(writer, "type", "buffer"); + + startElement(writer, "size"); + DPL::String pdSize = this->box.pdWidth + DPL::String(L"x") + + this->box.pdHeight; + writeText(writer, pdSize); + endElement(writer); + + startElement(writer, "script"); + writeAttribute(writer, "src", this->box.pdSrc); + endElement(writer); + + endElement(writer); + } + } + + endElement(writer); +} + +void Account::serialize(xmlTextWriterPtr writer) +{ + startElement(writer, "account"); + { + startElement(writer, "account-provider"); + writeAttribute(writer, "appid", this->provider.appid); + writeAttribute(writer, "multiple-accounts-support", + this->provider.multiAccount); + + FOREACH(i, this->provider.icon) + { + startElement(writer, "icon"); + writeAttribute(writer, "section", i->first); + writeText(writer, i->second); + endElement(writer); + } + + bool setDefaultLang = false; + FOREACH(n, this->provider.name) + { + if (!setDefaultLang && n->getLang() == L"en-gb") { + writeElement(writer, "label", n->getString()); + setDefaultLang = true; + } + writeElementWithOneAttribute(writer, "label", + n->getString(), "xml:lang", + n->getLang(), n->hasLang()); + } + if (!setDefaultLang) { + writeElement(writer, "label", this->provider.name.begin()->getString()); + } + + FOREACH(c, this->provider.capability) + { + startElement(writer, "capability"); + writeText(writer, *c); + endElement(writer); + } + endElement(writer); + } + endElement(writer); +} + +void Privilege::serialize(xmlTextWriterPtr writer) +{ + startElement(writer, "privileges"); + { + FOREACH(it, this->name) + { + startElement(writer, "privilege"); + writeText(writer, *it); + endElement(writer); + } + } + endElement(writer); +} + +void Metadata::serialize(xmlTextWriterPtr writer) +{ + startElement(writer, "metadata"); + writeAttribute(writer, "key", *this->key); + if (!this->value.IsNull()) { + writeAttribute(writer, "value", *this->value); + } + endElement(writer); +} +} //namespace Jobs +} //namespace WidgetInstall diff --git a/src_mobile/jobs/widget_install/manifest.h b/src_mobile/jobs/widget_install/manifest.h new file mode 100644 index 0000000..67ee3ce --- /dev/null +++ b/src_mobile/jobs/widget_install/manifest.h @@ -0,0 +1,586 @@ +/* + * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file manifest.h + * @author Mariusz Domanski (m.domanski@samsung.com) + */ + +#ifndef INSTALLER_JOBS_MANIFEST_H +#define INSTALLER_JOBS_MANIFEST_H + +#include + +#include +#include + +#include +#include +#include +#include + +namespace Jobs { +namespace WidgetInstall { +/** + * @brief string with optional language attribute + */ +class StringWithLang +{ + public: + StringWithLang() { } + StringWithLang(DPL::String s) : string(s) { } + StringWithLang(DPL::String s, DPL::String l) : string(s), lang(l) { } + DPL::String getString() + { + return this->string; + } + DPL::String getLang() + { + return this->lang; + } + bool hasLang() + { + return !this->lang.empty(); + } + int operator==(const StringWithLang &other) + { + return (DPL::ToUTF8String(other.string) == DPL::ToUTF8String(string)) && + (DPL::ToUTF8String(other.lang) == DPL::ToUTF8String(lang)); + } + + private: + DPL::String string; + DPL::String lang; +}; + +typedef StringWithLang LabelType, IconType, DescriptionType; + +/** + * These types are basicaly strings but they should allow usage of different + * range of characters or words (details in XML spec.). + * For simplicity DPL::Strings are used, although this can lead to XML + * validation + * errors (related to usage of not allowed characters in given places). + */ +typedef DPL::String NcnameType, NmtokenType, AnySimpleType, LangType; +typedef DPL::String OperationType, MimeType, UriType, TypeType, PackageType; +typedef DPL::OptionalString InstallLocationType, CategoriesType; +typedef DPL::String AppCategoryType; +typedef DPL::OptionalString KeyType, ValueType; + +/** + * xmllib2 wrappers + */ +void writeElement(xmlTextWriterPtr writer, const char * name, DPL::String body); +void writeText(xmlTextWriterPtr writer, DPL::String text); +void writeElement(xmlTextWriterPtr writer, const char * name, const char * body); +void writeElementWithOneAttribute(xmlTextWriterPtr writer, + const char * name, + const char * body, + const char * nameAttr, + DPL::String bodyAttr, + bool condition = true); +void startElement(xmlTextWriterPtr writer, const char * name); +void endElement(xmlTextWriterPtr writer); +void writeAttribute(xmlTextWriterPtr writer, const char * name, + DPL::String body, bool condition); +void writeAttribute(xmlTextWriterPtr writer, const char * name, + const char * body, bool condition); + +/** + * @brief author element + */ +class Author +{ + public: + Author() {} + Author(AnySimpleType e, + NcnameType h, + LangType l, + DPL::String b) : + email(e), href(h), lang(l), body(b) {} + void serialize(xmlTextWriterPtr writer); + + private: + AnySimpleType email; + NcnameType href; + LangType lang; + DPL::String body; +}; + +typedef Author AuthorType; + +/** + * @brief application-service element + */ +class AppControl +{ + public: + AppControl() {} + void addOperation(const OperationType &x) + { + this->operation.push_back(x); + } + void addUri(const UriType &x) + { + this->uri.push_back(x); + } + void addMime(const MimeType &x) + { + this->mime.push_back(x); + } + void serialize(xmlTextWriterPtr writer); + + private: + std::list operation; //attr name AnySimpleType + std::list uri; //attr name AnySimpleType + std::list mime; //attr name AnySimpleType +}; + +typedef AppControl AppControlType; + +/** + * @brief account element + */ +typedef std::list> IconListType; +typedef std::list DisplayNameListType; +typedef std::list AccountCapabilityType; + +struct AccountProvider +{ + NcnameType appid; + NcnameType multiAccount; + IconListType icon; + DisplayNameListType name; + AccountCapabilityType capability; +}; + +typedef AccountProvider AccountProviderType; + +class Account +{ + public: + Account() {} + void addAccountProvider(const AccountProvider &x) + { + this->provider = x; + } + void serialize(xmlTextWriterPtr writer); + + private: + AccountProviderType provider; +}; + +class Privilege +{ + public: + Privilege() {} + void addPrivilegeName(const DPL::String &x) + { + this->name.push_back(x); + } + bool isEmpty() + { + return this->name.empty(); + } + + void serialize(xmlTextWriterPtr writer); + + private: + std::list name; +}; + +typedef Privilege PrivilegeType; + +class Metadata +{ + public: + Metadata(KeyType k, ValueType v) : + key(k), + value(v) + {} + void serialize(xmlTextWriterPtr writer); + + private: + KeyType key; + ValueType value; +}; + +typedef Metadata MetadataType; + + +/** + * @brief ime-application element + */ +class ImeApplication +{ + public: + ImeApplication() {} + void setAppid(const NcnameType &x) + { + this->appid = x; + } + void setExec(const NcnameType &x) + { + this->exec = x; + } + void setMultiple(bool x) + { + this->multiple = x; + } + void setNodisplay(bool x) + { + this->nodisplay = x; + } + void setType(const TypeType &x) + { + this->type = x; + } + void addLabel(const LabelType &x) + { + this->label.push_back(x); + } + void addIcon(const IconType &x) + { + this->icon.push_back(x); + } + void serialize(xmlTextWriterPtr writer); + + private: + NcnameType appid; + NcnameType exec; + DPL::OptionalBool multiple; + DPL::OptionalBool nodisplay; + TypeType type; + std::list label; + std::list icon; +}; + +typedef ImeApplication ImeApplicationType; + +/** + * @brief service-application element + */ +class ServiceApplication +{ + public: + ServiceApplication() {} + void setAppid(const NcnameType &x) + { + this->appid = x; + } + void setAutoRestart(bool x) + { + this->autoRestart = x; + } + void setExec(const AnySimpleType &x) + { + this->exec = x; + } + void setOnBoot(bool x) + { + this->onBoot = x; + } + void setType(const TypeType &x) + { + this->type = x; + } + void addLabel(const LabelType &x) + { + this->label.push_back(x); + } + void addIcon(const IconType &x) + { + this->icon.push_back(x); + } + void addAppControl(const AppControlType &x) + { + this->appControl.push_back(x); + } + void serialize(xmlTextWriterPtr writer); + + private: + NcnameType appid; + DPL::OptionalBool autoRestart; + AnySimpleType exec; + DPL::OptionalBool onBoot; + TypeType type; + std::list label; //attr name AnySimpleType + std::list icon; //attr name AnySimpleType + std::list appControl; //attr name AnySimpleType +}; + +typedef ServiceApplication ServiceApplicationType; + +/** + * @brief ui-application element + */ +class UiApplication +{ + public: + UiApplication() {} + void setAppid(const NcnameType &x) + { + this->appid = x; + } + void setExtraid(const NcnameType &x) + { + this->extraid = x; + } + void setExec(const AnySimpleType &x) + { + this->exec = x; + } + void setMultiple(bool x) + { + this->multiple = x; + } + void setNodisplay(bool x) + { + this->nodisplay = x; + } + void setTaskmanage(bool x) + { + this->taskmanage = x; + } + void setType(const TypeType &x) + { + this->type = x; + } + void setCategories(const NcnameType &x) + { + this->categories = x; + } + void addLabel(const LabelType &x) + { + this->label.push_back(x); + } + void addIcon(const IconType &x) + { + this->icon.push_back(x); + } + void addAppControl(const AppControlType &x) + { + this->appControl.push_back(x); + } + void addAppCategory(const AppCategoryType &x) + { + this->appCategory.push_back(x); + } + void addMetadata(const MetadataType &m) + { + this->metadata.push_back(m); + } + void serialize(xmlTextWriterPtr writer); + + private: + NcnameType appid; + NcnameType extraid; + AnySimpleType exec; + DPL::OptionalBool multiple; + DPL::OptionalBool nodisplay; + DPL::OptionalBool taskmanage; + TypeType type; + CategoriesType categories; + std::list label; + std::list icon; + std::list appControl; + std::list appCategory; + std::list metadata; +}; + +typedef UiApplication UiApplicationType; + +/** + * @brief LiveBox element + */ +typedef WrtDB::ConfigParserData::LiveboxInfo::BoxSizeList BoxSizeType; +typedef WrtDB::ConfigParserData::LiveboxInfo::BoxLabelList BoxLabelType; + +struct BoxInfo +{ + NcnameType boxSrc; + NcnameType boxMouseEvent; + NcnameType boxTouchEffect; + BoxSizeType boxSize; + NcnameType pdSrc; + NcnameType pdWidth; + NcnameType pdHeight; +}; +typedef BoxInfo BoxInfoType; + +class LiveBox +{ + public: + LiveBox() { } + void setLiveboxId(const NcnameType &x) + { + this->liveboxId = x; + } + void setPrimary(const NcnameType &x) + { + this->primary = x; + } + void setUpdatePeriod(const NcnameType &x) + { + this->updatePeriod = x; + } + void setLabel(const BoxLabelType &x) + { + this->label = x; + } + void setIcon(const NcnameType &x) + { + this->icon = x; + } + void setBox(const BoxInfoType &x) + { + this->box = x; + } + + void serialize(xmlTextWriterPtr writer); + + private: + NcnameType liveboxId; + NcnameType primary; + NcnameType autoLaunch; + NcnameType updatePeriod; + NcnameType timeout; + BoxLabelType label; + NcnameType icon; + NcnameType lang; + BoxInfoType box; +}; + +typedef LiveBox LiveBoxInfo; + +/** + * @brief manifest element + * + * Manifest xml file representation. + */ +class Manifest +{ + public: + Manifest() {} + void serialize(xmlTextWriterPtr writer); + void generate(DPL::String filename); + + void addLabel(const LabelType &x) + { +#ifdef MULTIPROCESS_SERVICE_SUPPORT + auto pos = std::find(label.begin(), label.end(), x); + if (pos == label.end()) { + this->label.push_back(x); + } +#else + this->label.push_back(x); +#endif + } + void addIcon(const IconType &x) + { + this->icon.push_back(x); + } + void addAuthor(const AuthorType &x) + { + this->author.push_back(x); + } + void addDescription(const DescriptionType &x) + { + this->description.push_back(x); + } + // void addCompatibility(const CompatibilityType &x) + // { + // this->compatibility.push_back(x); + // } + // void addDeviceProfile(const DeviceProfileType &x) + // { + // this->deviceProfile.push_back(x); + // } + void addServiceApplication(const ServiceApplicationType &x) + { + this->serviceApplication.push_back(x); + } + void addUiApplication(const UiApplicationType &x) + { + this->uiApplication.push_back(x); + } + void addImeApplication(const ImeApplicationType &x) + { + this->imeApplication.push_back(x); + } + // void addFont(const FontType &x) { this->font.push_back(x); } + + void addLivebox(const LiveBoxInfo &x) + { + this->livebox.push_back(x); + } + + void addAccount(const Account &x) + { + this->account.push_back(x); + } + + void addPrivileges(const PrivilegeType &x) + { + this->privileges = x; + } + + void setInstallLocation(const InstallLocationType &x) + { + this->installLocation = x; + } + void setPackage(const NcnameType &x) + { + this->package = x; + } + void setType(const PackageType &x) + { + this->type = x; + } + void setVersion(const NmtokenType &x) + { + this->version = x; + } + void setStoreClientId(const NcnameType &x) + { + this->storeClientId= x; + } + + private: + std::list label; + std::list icon; + std::list author; + std::list description; + // std::list compatibility; + // std::list deviceProfile; + std::list serviceApplication; + std::list uiApplication; + std::list imeApplication; + // std::list font; + std::list livebox; + InstallLocationType installLocation; + NcnameType package; + PackageType type; + NmtokenType version; + std::list account; + PrivilegeType privileges; + NcnameType storeClientId; + +}; +} //namespace Jobs +} //namespace WidgetInstall + +#endif //INSTALLER_JOBS_MANIFEST_H diff --git a/src_mobile/jobs/widget_install/task_ace_check.cpp b/src_mobile/jobs/widget_install/task_ace_check.cpp new file mode 100644 index 0000000..cf44fc0 --- /dev/null +++ b/src_mobile/jobs/widget_install/task_ace_check.cpp @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file task_ace_check.cpp + * @author Pawel Sikorski (p.sikorski@samsung.com) + * @version 1.0 + * @brief Implementation file for installer task ace check + */ + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include + +namespace Jobs { +namespace WidgetInstall { +TaskAceCheck::TaskAceCheck(InstallerContext& context) : + DPL::TaskDecl(this), + m_context(context) +{ + AddStep(&TaskAceCheck::StartStep); + AddStep(&TaskAceCheck::StepPrepareForAce); + AddStep(&TaskAceCheck::StepAceCheck); + AddStep(&TaskAceCheck::StepProcessAceResponse); + AddStep(&TaskAceCheck::StepCheckAceResponse); + AddStep(&TaskAceCheck::EndStep); +} + +void TaskAceCheck::StepPrepareForAce() +{ + m_context.featureLogic = + FeatureLogicPtr(new FeatureLogic(m_context.widgetConfig.tzAppid)); + m_context.job->UpdateProgress( + InstallerContext::INSTALL_ACE_PREPARE, + "Widget Access Control Check Prepared"); +} + +void TaskAceCheck::StepAceCheck() +{ + WrtDB::WidgetDAO dao(m_context.widgetConfig.tzAppid); + _D("StepAceCheck!"); + // This widget does not use any device cap + if (m_context.featureLogic->isDone()) { + return; + } + + _D("StepAceCheck!"); + DPL::String deviceCap = m_context.featureLogic->getDevice(); + + _D("StepAceCheck!"); + _D("DevCap is : %ls", deviceCap.c_str()); + + std::string devCapStr = DPL::ToUTF8String(deviceCap); + ace_policy_result_t policyResult = ACE_DENY; + + //TODO: remove dao.getHandle() + if (m_context.mode.installTime == InstallMode::InstallTime::PRELOAD) { + _D("This widget is preloaded. So ace check will be skiped"); + policyResult = ACE_PERMIT; + } else { + ace_return_t ret = ace_get_policy_result( + const_cast(devCapStr.c_str()), + dao.getHandle(), + &policyResult); + if (ACE_OK != ret) { + ThrowMsg(Exceptions::AceCheckFailed, "Instalation failure. " + "ACE check failure"); + } + } + + _D("PolicyResult is : %d", static_cast(policyResult)); + m_context.staticPermittedDevCaps.insert(std::make_pair(deviceCap, + policyResult == + ACE_PERMIT)); + + m_context.featureLogic->setAceResponse(policyResult != ACE_DENY); +} + +void TaskAceCheck::StepProcessAceResponse() +{ + WrtDB::WidgetDAO dao(m_context.widgetConfig.tzAppid); + if (m_context.widgetConfig.packagingType == + WrtDB::PKG_TYPE_HOSTED_WEB_APP) + { + return; + } + + _D("StepProcessAceResponse"); + m_context.featureLogic->next(); + + // No device caps left to process + if (m_context.featureLogic->isDone()) { + _D("All responses has been received from ACE."); + // Data to convert to C API + std::vector devCaps; + std::vector devCapsSmack; + // Saving static dev cap permissions + FOREACH(cap, m_context.staticPermittedDevCaps) { + _D("staticPermittedDevCaps : %ls smack: %d", cap->first.c_str(), cap->second); + std::string devCapStr = DPL::ToUTF8String(cap->first); + devCaps.push_back(devCapStr); + devCapsSmack.push_back(cap->second); + } + ace_requested_dev_cap_list_t list; + list.count = devCaps.size(); + list.items = new ace_requested_dev_cap_t[list.count]; + + for (unsigned int i = 0; i < devCaps.size(); ++i) { + list.items[i].device_capability = + const_cast(devCaps[i].c_str()); + list.items[i].smack_granted = + devCapsSmack[i] ? ACE_TRUE : ACE_FALSE; + } + //TODO: remove dao.getHandle() + ace_return_t ret = ace_set_requested_dev_caps(dao.getHandle(), + &list); + if (ACE_OK != ret) { + ThrowMsg(Exceptions::AceCheckFailed, "Instalation failure. " + "ACE failure"); + } + delete[] list.items; + + std::set acceptedFeature; + auto it = m_context.featureLogic->resultBegin(); + for (; it != m_context.featureLogic->resultEnd(); ++it) { + if (!(it->rejected)) { + acceptedFeature.insert(DPL::ToUTF8String(it->name)); + } + } + ace_feature_list_t featureList; + featureList.count = acceptedFeature.size(); + featureList.items = new ace_string_t[featureList.count]; + + size_t i = 0; + for (std::set::const_iterator iter = acceptedFeature.begin(); + iter != acceptedFeature.end(); ++iter) + { + _D("Accepted feature item: %s", iter->c_str()); + featureList.items[i] = const_cast(iter->c_str()); + i++; + } + + //TODO: remove dao.getHandle() + ret = ace_set_accepted_feature(dao.getHandle(), &featureList); + + delete[] featureList.items; + + if (ACE_OK != ret) { + _E("Error in ace_set_feature"); + ThrowMsg(Exceptions::AceCheckFailed, "Instalation failure. " + "ace_set_feature failure."); + } + return; + } + + _D("Next device cap."); + // Process next device cap + SwitchToStep(&TaskAceCheck::StepAceCheck); +} + +void TaskAceCheck::StepCheckAceResponse() +{ + _D("Checking ACE response"); + if (m_context.featureLogic->isRejected()) { + _E("Installation failure. Some devCap was not accepted by ACE."); + ThrowMsg( + Exceptions::PrivilegeLevelViolation, + "Instalation failure. " + "Some deviceCap was not accepted by ACE."); + } + _D("Updating \"feature reject status\" in database!"); + auto it = m_context.featureLogic->resultBegin(); + auto end = m_context.featureLogic->resultEnd(); + for (; it != end; ++it) { + _D(" |- Feature: %ls has reject status: %d", it->name.c_str(), it->rejected); + if (it->rejected) { + WrtDB::WidgetDAO dao(m_context.widgetConfig.tzAppid); + dao.updateFeatureRejectStatus(*it); + } + } + _D("Installation continues..."); +} + +void TaskAceCheck::StartStep() +{ + _D("--------- : START ----------"); +} + +void TaskAceCheck::EndStep() +{ + m_context.job->UpdateProgress( + InstallerContext::INSTALL_ACE_CHECK, + "Widget Access Control Check Finished"); + + _D("--------- : END ----------"); +} +} //namespace WidgetInstall +} //namespace Jobs diff --git a/src_mobile/jobs/widget_install/task_ace_check.h b/src_mobile/jobs/widget_install/task_ace_check.h new file mode 100644 index 0000000..e4ce90d --- /dev/null +++ b/src_mobile/jobs/widget_install/task_ace_check.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file task_ace_check.h + * @author Pawel Sikorski (p.sikorski@samsung.com) + * @version 1.0 + * @brief Header file for installer task ace check + */ +#ifndef INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_ACE_CHECK_H +#define INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_ACE_CHECK_H + +#include + +class InstallerContext; + +namespace Jobs { +namespace WidgetInstall { +class TaskAceCheck : + public DPL::TaskDecl +{ + private: + InstallerContext& m_context; + + void StepPrepareForAce(); + void StepAceCheck(); + void StepProcessAceResponse(); + void StepCheckAceResponse(); + + void StartStep(); + void EndStep(); + + public: + TaskAceCheck(InstallerContext& context); +}; +} //namespace WidgetInstall +} //namespace Jobs + +#endif /* INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_ACE_CHECK_H */ diff --git a/src_mobile/jobs/widget_install/task_certify.cpp b/src_mobile/jobs/widget_install/task_certify.cpp new file mode 100644 index 0000000..81f21b0 --- /dev/null +++ b/src_mobile/jobs/widget_install/task_certify.cpp @@ -0,0 +1,362 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file task_certify.cpp + * @author Pawel Sikorski (p.sikorski@samgsung.com) + * @version + * @brief + */ + +//SYSTEM INCLUDES +#include +#include +#include +#include +#include +#include + +//WRT INCLUDES +#include +#include +#include +#include +#include +#include "wac_widget_id.h" + +#include +#include +#include +#include +#include + +#include +#include + +#include + +using namespace ValidationCore; +using namespace WrtDB; + +namespace { + +WidgetCertificateData toWidgetCertificateData(const SignatureData &data, + bool root) +{ + WidgetCertificateData result; + + result.chainId = data.getSignatureNumber(); + _D("result.chainId : %d", result.chainId); + + result.owner = data.isAuthorSignature() ? + WidgetCertificateData::AUTHOR : WidgetCertificateData::DISTRIBUTOR; + + result.type = root ? + WidgetCertificateData::ROOT : WidgetCertificateData::ENDENTITY; + + CertificatePtr certificate; + + if (root) { + certificate = data.getRootCaCertificatePtr(); + } else { + certificate = data.getEndEntityCertificatePtr(); + } + + Assert(certificate && !certificate->getCommonName().IsNull() && + "CommonName is Null"); + + result.strCommonName = *certificate->getCommonName(); + + result.strMD5Fingerprint = std::string("md5 ") + + Certificate::FingerprintToColonHex( + certificate->getFingerprint(Certificate::FINGERPRINT_MD5)); + + result.strSHA1Fingerprint = std::string("sha-1 ") + + Certificate::FingerprintToColonHex( + certificate->getFingerprint(Certificate::FINGERPRINT_SHA1)); + + return result; +} + +CertificatePtr getOldAuthorSignerCertificate(DPL::String appid) +{ + WidgetDAOReadOnly dao(appid); + CertificateChainList chainList = dao.getWidgetCertificate(SIGNATURE_AUTHOR); + + FOREACH(it, chainList) + { + ValidationCore::CertificateCollection chain; + if (false == chain.load(*it)) { + _E("Chain is broken"); + } + + if (!chain.sort()) { + _E("Chain failed at sorting"); + } + + ValidationCore::CertificateList list = chain.getCertificateList(); + + FOREACH(cert, list) + { + if (!(*cert)->isRootCert() && !(*cert)->isCA()) { + return *cert; + } + } + } + return CertificatePtr(NULL); +} +} // namespace anonymous + +namespace Jobs { +namespace WidgetInstall { +TaskCertify::TaskCertify(InstallerContext &inCont) : + DPL::TaskDecl(this), + m_contextData(inCont) +{ + AddStep(&TaskCertify::StartStep); + AddStep(&TaskCertify::stepSignature); + // certi comparison determines whether the update. + if (true == m_contextData.isUpdateMode) { + AddStep(&TaskCertify::stepVerifyUpdate); + } + AddStep(&TaskCertify::EndStep); +} + +void TaskCertify::processDistributorSignature(const SignatureData &data) +{ + // this signature is verified - + // no point in check domain WAC_ROOT and WAC_RECOGNIZED + m_contextData.widgetSecurity.setDistributorSigned(true); + + CertificateCollection collection; + collection.load(data.getCertList()); + Assert(collection.sort() && + "Certificate collection can't sort"); + + Assert(collection.isChain() && + "Certificate collection is not able to create chain. " + "It is not possible to verify this signature."); + + m_contextData.widgetSecurity.getCertificateChainListRef().push_back( + collection); + + if (data.getSignatureNumber() == 1) { + m_contextData.widgetSecurity.getCertificateListRef().push_back( + toWidgetCertificateData(data, true)); + m_contextData.widgetSecurity.getCertificateListRef().push_back( + toWidgetCertificateData(data, false)); + } +} + +void TaskCertify::processAuthorSignature(const SignatureData &data) +{ + using namespace ValidationCore; + _D("DNS Identity match!"); + // this signature is verified or widget is distributor signed + m_contextData.widgetSecurity.setAuthorCertificatePtr(data.getEndEntityCertificatePtr()); + CertificatePtr test = m_contextData.widgetSecurity.getAuthorCertificatePtr(); + + m_contextData.widgetSecurity.getCertificateListRef().push_back( + toWidgetCertificateData(data, true)); + m_contextData.widgetSecurity.getCertificateListRef().push_back( + toWidgetCertificateData(data, false)); + + // match widget_id with one from dns identity set + WacWidgetId widgetId(m_contextData.widgetConfig.configInfo.widget_id); + + CertificatePtr cert = data.getEndEntityCertificatePtr(); + Assert(cert); + Certificate::AltNameSet dnsIdentity = cert->getAlternativeNameDNS(); + + CertificateCollection collection; + collection.load(data.getCertList()); + collection.sort(); + Assert(collection.isChain() && + "Certificate collection is not able to create chain. " + "It is not possible to verify this signature."); + + m_contextData.widgetSecurity.getAuthorsCertificateChainListRef().push_back( + collection); + + FOREACH(it, dnsIdentity){ + if (widgetId.matchHost(*it)) { + m_contextData.widgetSecurity.setRecognized(true); + return; + } + } +} + +void TaskCertify::getSignatureFiles(std::string path, SignatureFileInfoSet& file) +{ + _D("path : %s", path.c_str()); + SignatureFileInfoSet signatureFiles; + SignatureFinder signatureFinder(path); + if (SignatureFinder::NO_ERROR != signatureFinder.find(file)) { + _E("Error in Signature Finder : %s", path.c_str()); + ThrowMsg(Exceptions::SignatureNotFound, + "Error openig temporary widget directory"); + } +} + +void TaskCertify::stepSignature() +{ + _D("================ Step: <> ENTER ==============="); + + std::string widgetPath; + widgetPath = m_contextData.locations->getPackageInstallationDir() + "/"; + + SignatureFileInfoSet signatureFiles; + + Try { + getSignatureFiles(widgetPath, signatureFiles); + + if (signatureFiles.size() <= 0) { + widgetPath += std::string(WrtDB::GlobalConfig::GetWidgetSrcPath()) + + "/"; + if (0 == access(widgetPath.c_str(), F_OK)) { + getSignatureFiles(widgetPath, signatureFiles); + } + } + } Catch(Exceptions::SignatureNotFound) { + ReThrowMsg(Exceptions::SignatureNotFound, widgetPath); + } + + SignatureFileInfoSet::reverse_iterator iter = signatureFiles.rbegin(); + _D("Number of signatures: %d", signatureFiles.size()); + + for (; iter != signatureFiles.rend(); ++iter) { + _D("Checking signature with id=%d", iter->getFileNumber()); + SignatureData data(widgetPath + iter->getFileName(), + iter->getFileNumber()); + + Try { + SignatureReader xml; + xml.initialize(data, GlobalConfig::GetSignatureXmlSchema()); + xml.read(data); + + WrtSignatureValidator::Result result; + + WrtSignatureValidator validator( + WrtSignatureValidator::TIZEN, + !GlobalSettings:: + OCSPTestModeEnabled(), + !GlobalSettings:: + CrlTestModeEnabled(), + false); + + result = validator.check(data, widgetPath); + + if (m_contextData.mode.installTime + == InstallMode::InstallTime::PRELOAD) + { + result = WrtSignatureValidator::SIGNATURE_VERIFIED; + } + + if (result == WrtSignatureValidator::SIGNATURE_REVOKED) { + _W("Certificate is REVOKED"); + ThrowMsg(Exceptions::CertificateExpired, + "Certificate is REVOKED"); + } + + if (result == WrtSignatureValidator::SIGNATURE_INVALID && + iter->getFileNumber() <= 1) { + _W("Signature is INVALID"); + // TODO change exception name + ThrowMsg(Exceptions::SignatureInvalid, + "Invalid Package"); + } + + if (data.isAuthorSignature()) { + if (result == WrtSignatureValidator::SIGNATURE_VERIFIED ) { + processAuthorSignature(data); + } + } else { + if (result != WrtSignatureValidator::SIGNATURE_INVALID) { + processDistributorSignature(data); + } + } + } Catch(ParserSchemaException::Base) { + _E("Error occured in ParserSchema."); + ReThrowMsg(Exceptions::SignatureInvalid, + "Error occured in ParserSchema."); + } + } + + if (signatureFiles.empty()) { + _D("No signature files has been found."); + } + + _D("================ Step: <> DONE ================"); + + m_contextData.job->UpdateProgress( + InstallerContext::INSTALL_DIGSIG_CHECK, + "Widget Signature checked"); +} + +bool TaskCertify::isTizenWebApp() const +{ + bool ret = FALSE; + if (m_contextData.widgetConfig.webAppType.appType + == WrtDB::AppType::APP_TYPE_TIZENWEBAPP) + { + ret = TRUE; + } + + return ret; +} + +void TaskCertify::stepVerifyUpdate() +{ + _D("Step: <>"); + CertificatePtr newCertificate = + m_contextData.widgetSecurity.getAuthorCertificatePtr(); + CertificatePtr oldCertificate = + getOldAuthorSignerCertificate(m_contextData.widgetConfig.tzAppid); + + if (!!newCertificate && !!oldCertificate) { + if (0 != newCertificate->getBase64().compare(oldCertificate->getBase64())) { + _D("old widget's author signer certificate : %s", (oldCertificate->getBase64()).c_str()); + _D("new widget's author signer certificate : %s", (newCertificate->getBase64()).c_str()); + ThrowMsg(Exceptions::NotMatchedCertification, + "Author signer certificates doesn't match \ + between old widget and installing widget"); + } + } else { + if (!(NULL == newCertificate.Get() && NULL == oldCertificate.Get())) { + ThrowMsg(Exceptions::NotMatchedCertification, + "Author signer certificates doesn't match \ + between old widget and installing widget"); + } + } +} + +void TaskCertify::StartStep() +{ + _D("--------- : START ----------"); +} + +void TaskCertify::EndStep() +{ + _D("Step: <>"); + + m_contextData.job->UpdateProgress( + InstallerContext::INSTALL_CERT_CHECK, + "Widget Certification Check Finished"); + + _D("--------- : END ----------"); +} +} //namespace WidgetInstall +} //namespace Jobs + diff --git a/src_mobile/jobs/widget_install/task_certify.h b/src_mobile/jobs/widget_install/task_certify.h new file mode 100644 index 0000000..6a59781 --- /dev/null +++ b/src_mobile/jobs/widget_install/task_certify.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file task_certify.h + * @author Pawel Sikorski (p.sikorski@samgsung.com) + * @version + * @brief + */ +#ifndef INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_CERTIFY_H +#define INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_CERTIFY_H + +//SYSTEM INCLUDES +#include +#include +#include + +//WRT INCLUDES +#include + +class InstallerContext; + +namespace ValidationCore { +class SignatureData; +} + +namespace Jobs { +namespace WidgetInstall { +class TaskCertify : + public DPL::TaskDecl +{ + public: + TaskCertify(InstallerContext &inCont); + + private: + //data + InstallerContext& m_contextData; + + //steps + void stepSignature(); + void stepVerifyUpdate(); + + void StartStep(); + void EndStep(); + + void processDistributorSignature(const ValidationCore::SignatureData &data); + void processAuthorSignature(const ValidationCore::SignatureData &data); + void getSignatureFiles(std::string path, + ValidationCore::SignatureFileInfoSet& file); + + bool isTizenWebApp() const; +}; +} //namespace WidgetInstall +} //namespace Jobs + +#endif // INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_CERTIFY_H diff --git a/src_mobile/jobs/widget_install/task_certify_level.cpp b/src_mobile/jobs/widget_install/task_certify_level.cpp new file mode 100644 index 0000000..9d1bc50 --- /dev/null +++ b/src_mobile/jobs/widget_install/task_certify_level.cpp @@ -0,0 +1,264 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file task_certify_level.cpp + * @author Jihoon Chung (jihoon.chung@samgsung.com) + * @version + * @brief + */ + +//SYSTEM INCLUDES +#include +#include +#include + +//WRT INCLUDES +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +using namespace ValidationCore; +using namespace WrtDB; + +namespace Jobs { +namespace WidgetInstall { +TaskCertifyLevel::TaskCertifyLevel(InstallerContext &inCont) : + DPL::TaskDecl(this), + m_contextData(inCont) +{ + AddStep(&TaskCertifyLevel::StartStep); + AddStep(&TaskCertifyLevel::stepCertifyLevel); + AddStep(&TaskCertifyLevel::EndStep); +} + +void TaskCertifyLevel::stepCertifyLevel() +{ + _D("================ Step: <> ENTER ==============="); + if (!checkConfigurationLevel(getCertifyLevel())) { + ThrowMsg(Exceptions::PrivilegeLevelViolation, "setting level violate"); + } + _D("================ Step: <> DONE ================"); +} + +void TaskCertifyLevel::getSignatureFiles(const std::string& path, + SignatureFileInfoSet& file) +{ + SignatureFileInfoSet signatureFiles; + SignatureFinder signatureFinder(path); + if (SignatureFinder::NO_ERROR != signatureFinder.find(file)) { + _E("Error in Signature Finder : %s", path.c_str()); + ThrowMsg(Exceptions::SignatureNotFound, "Signature not found"); + } +} + +TaskCertifyLevel::Level TaskCertifyLevel::getCertifyLevel() +{ + std::string widgetPath = m_contextData.locations->getPackageInstallationDir() + "/"; + SignatureFileInfoSet signatureFiles; + + Try { + getSignatureFiles(widgetPath, signatureFiles); + + if (signatureFiles.size() <= 0) { + widgetPath += std::string(WrtDB::GlobalConfig::GetWidgetSrcPath()) + + "/"; + if (0 == access(widgetPath.c_str(), F_OK)) { + getSignatureFiles(widgetPath, signatureFiles); + } + } + } Catch(Exceptions::SignatureNotFound) { + ReThrowMsg(Exceptions::SignatureNotFound, widgetPath); + } + + SignatureFileInfoSet::reverse_iterator iter = signatureFiles.rbegin(); + _D("Number of signatures: %d", signatureFiles.size()); + + Level level = Level::UNKNOWN; + for (; iter != signatureFiles.rend(); ++iter) { + _D("Checking signature with id=%d", iter->getFileNumber()); + SignatureData data(widgetPath + iter->getFileName(), + iter->getFileNumber()); + + Try { + SignatureReader xml; + xml.initialize(data, GlobalConfig::GetSignatureXmlSchema()); + xml.read(data); + + WrtSignatureValidator validator( + WrtSignatureValidator::TIZEN, + !GlobalSettings:: + OCSPTestModeEnabled(), + !GlobalSettings:: + CrlTestModeEnabled(), + false); + + WrtSignatureValidator::Result result = + validator.check(data, widgetPath); + + if (m_contextData.mode.installTime + == InstallMode::InstallTime::PRELOAD) + { + result = WrtSignatureValidator::SIGNATURE_VERIFIED; + } + + if (result == WrtSignatureValidator::SIGNATURE_REVOKED) { + ThrowMsg(Exceptions::CertificateExpired, + "Certificate is REVOKED"); + } + + if (result == WrtSignatureValidator::SIGNATURE_INVALID && + iter->getFileNumber() <= 1) + { + ThrowMsg(Exceptions::SignatureInvalid, "Invalid Package"); + } + + if (data.isAuthorSignature()) { + _D("Skip author signature"); + } else { + Level currentCertLevel = + certTypeToLevel(data.getVisibilityLevel()); + if (currentCertLevel == Level::UNKNOWN) { + continue; + } + if (currentCertLevel > level) { + level = currentCertLevel; + _D("level %s", enumToString(level).c_str()); + } + } + } Catch(ParserSchemaException::Base) { + _E("Error occured in ParserSchema."); + ReThrowMsg(Exceptions::SignatureInvalid, + "Error occured in ParserSchema."); + } + } + + m_contextData.certLevel = level; + return level; +} + +bool TaskCertifyLevel::checkConfigurationLevel( + TaskCertifyLevel::Level level) +{ + if (!checkSettingLevel(level)) { + return false; + } + if (!checkAppcontrolHasDisposition(level)) { + return false; + } + return true; +} + +bool TaskCertifyLevel::checkSettingLevel( + TaskCertifyLevel::Level level) +{ + secureSettingMap data = { + {"sound-mode", Level::PARTNER}, + {"nodisplay", Level::PARTNER} + }; + FOREACH(it, m_contextData.widgetConfig.configInfo.settingsList) { + secureSettingIter ret = data.find(DPL::ToUTF8String(it->m_name)); + if (ret != data.end()) { + if (level < ret->second) { + _E("\"%ls\" needs \"%s\" level", it->m_name.c_str(), enumToString(ret->second).c_str()); + return false; + } + } + } + return true; +} + +bool TaskCertifyLevel::checkAppcontrolHasDisposition( + TaskCertifyLevel::Level level) +{ + // tizen:disposition -> platform + FOREACH(it, m_contextData.widgetConfig.configInfo.appControlList) { + if (ConfigParserData::AppControlInfo::Disposition::UNDEFINE != + it->m_disposition) + { + if (level < Level::PLATFORM) { + _E("\"tizen:disposition\" needs \"%s \" level", enumToString(Level::PLATFORM).c_str()); + return false; + } + } + } + return true; +} + +std::string TaskCertifyLevel::enumToString( + TaskCertifyLevel::Level level) +{ + switch (level) { +#define X(x, y) case x: return #y; + X(Level::UNKNOWN, UNKNOWN) + X(Level::PUBLIC, PUBLIC) + X(Level::PARTNER, PARTNER) + X(Level::PLATFORM, PLATFORM) +#undef X + default: + return "UNKNOWN"; + } +} + +TaskCertifyLevel::Level TaskCertifyLevel::certTypeToLevel( + CertStoreId::Type type) +{ + // CertStoreType.h (framework/security/cert-svc) + // RootCA's visibility level : public + // const Type VIS_PUBLIC = 1 << 6; + // RootCA's visibility level : partner + // const Type VIS_PARTNER = 1 << 7; + // RootCA's visibility level : platform + // const Type VIS_PLATFORM = 1 << 10; + if (type == CertStoreId::VIS_PUBLIC) { + return Level::PUBLIC; + } else if (type == CertStoreId::VIS_PARTNER) { + return Level::PARTNER; + } else if (type == CertStoreId::VIS_PLATFORM) { + return Level::PLATFORM; + } + return Level::UNKNOWN; +} + +void TaskCertifyLevel::StartStep() +{ + _D("--------- : START ----------"); +} + +void TaskCertifyLevel::EndStep() +{ + _D("--------- : END ----------"); + + m_contextData.job->UpdateProgress( + InstallerContext::INSTALL_CERTIFY_LEVEL_CHECK, + "Application Certificate level check Finished"); +} +} //namespace WidgetInstall +} //namespace Jobs + diff --git a/src_mobile/jobs/widget_install/task_certify_level.h b/src_mobile/jobs/widget_install/task_certify_level.h new file mode 100644 index 0000000..ad8d427 --- /dev/null +++ b/src_mobile/jobs/widget_install/task_certify_level.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file task_certify_level.h + * @author Jihoon Chung (jihoon.chung@samgsung.com) + * @version + * @brief + */ +#ifndef INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_CERTIFY_LEVEL_H +#define INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_CERTIFY_LEVEL_H + +//SYSTEM INCLUDES +#include +#include +#include + +//WRT INCLUDES +#include +#include +#include + +class InstallerContext; + +namespace Jobs { +namespace WidgetInstall { +class TaskCertifyLevel : + public DPL::TaskDecl +{ + public: + TaskCertifyLevel(InstallerContext &inCont); + + private: + //data + InstallerContext& m_contextData; + + enum Level { + UNKNOWN = 0, + PUBLIC = 1, + PARTNER = 2, + PLATFORM = 3 + }; + typedef std::map secureSettingMap; + typedef std::map::iterator secureSettingIter; + + //steps + void stepCertifyLevel(); + void StartStep(); + void EndStep(); + + //util + void getSignatureFiles(const std::string& path, + ValidationCore::SignatureFileInfoSet& file); + Level getCertifyLevel(); + bool checkConfigurationLevel(Level level); + bool checkSettingLevel(Level level); + bool checkAppcontrolHasDisposition(Level level); + std::string enumToString(Level level); + Level certTypeToLevel(ValidationCore::CertStoreId::Type type); + +}; +} //namespace WidgetInstall +} //namespace Jobs + +#endif // INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_CERTIFY_LEVEL_H diff --git a/src_mobile/jobs/widget_install/task_commons.cpp b/src_mobile/jobs/widget_install/task_commons.cpp new file mode 100644 index 0000000..c5b5b67 --- /dev/null +++ b/src_mobile/jobs/widget_install/task_commons.cpp @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file task_commons.cpp + * @author Krzysztof Jackiewicz (k.jackiewicz@samsung.com) + * @version 1.0 + */ + +#include "task_commons.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Jobs { +namespace WidgetInstall { +namespace { +const char * const TEMPORARY_PATH_POSTFIX = "temp"; +const mode_t TEMPORARY_PATH_MODE = 0775; +} // namespace + +std::string createTempPath(bool preload) +{ + _D("Step: Creating temporary path"); + + // Temporary path + std::ostringstream tempPathBuilder; + + if (preload) { + tempPathBuilder << WrtDB::GlobalConfig::GetUserPreloadedWidgetPath(); + } else { + tempPathBuilder << WrtDB::GlobalConfig::GetUserInstalledWidgetPath(); + } + tempPathBuilder << WrtDB::GlobalConfig::GetTmpDirPath(); + tempPathBuilder << "/"; + tempPathBuilder << TEMPORARY_PATH_POSTFIX; + tempPathBuilder << "_"; + + timeval tv; + gettimeofday(&tv, NULL); + tempPathBuilder << + (static_cast(tv.tv_sec) * 1000000ULL + + static_cast(tv.tv_usec)); + + std::string tempPath = tempPathBuilder.str(); + + // Remove old path if any + struct stat fileInfo; + + if (stat(tempPath.c_str(), &fileInfo) == 0) { + if (!WrtUtilRemove(tempPath)) { + ThrowMsg(Exceptions::RemovingFolderFailure, + "Failed to to remove temporary directory"); + } + } + // Create new path + if (!WrtUtilMakeDir(tempPath, TEMPORARY_PATH_MODE)) { + ThrowMsg(Exceptions::FileOperationFailed, + "Failed to create temporary directory"); + } + + return tempPath; +} + +void createTempPath(const std::string& path) +{ + if (!WrtUtilMakeDir(path, TEMPORARY_PATH_MODE)) { + ThrowMsg(Exceptions::FileOperationFailed, + "Failed to create temporary directory"); + } +} +} // WidgetInstall +} // Jobs diff --git a/src_mobile/jobs/widget_install/task_commons.h b/src_mobile/jobs/widget_install/task_commons.h new file mode 100644 index 0000000..caf9660 --- /dev/null +++ b/src_mobile/jobs/widget_install/task_commons.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file task_commons.h + * @author Krzysztof Jackiewicz (k.jackiewicz@samsung.com) + * @version 1.0 + */ + +#ifndef INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_COMMONS_H_ +#define INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_COMMONS_H_ + +#include + +namespace Jobs { +namespace WidgetInstall { +//TODO make directory like jobs common? + +std::string createTempPath(bool isReadOnly = false); +void createTempPath(const std::string& path); +} // WidgetInstall +} // Jobs + +#endif /* INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_COMMONS_H_ */ diff --git a/src_mobile/jobs/widget_install/task_configuration.cpp b/src_mobile/jobs/widget_install/task_configuration.cpp new file mode 100644 index 0000000..c336848 --- /dev/null +++ b/src_mobile/jobs/widget_install/task_configuration.cpp @@ -0,0 +1,665 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file task_configuration.cpp + * @version 1.0 + * @author Tomasz Iwanek + * @brief implementation file for configuration task + */ +#include "task_configuration.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "root_parser.h" +#include "widget_parser.h" +#include "parser_runner.h" + +#include +#include +#include +#include +#include +#include + +#include + +using namespace WrtDB; + +namespace { +const char* const CONFIG_XML = "config.xml"; +const char* const WITH_OSP_XML = "res/wgt/config.xml"; +const char* const OSP_MANIFEST_XML = "info/manifest.xml"; + +//allowed: a-z, A-Z, 0-9 +const char* REG_TIZENID_PATTERN = "^[a-zA-Z0-9]{10}.{1,}$"; +const char* REG_PKGID_PATTERN = "^[a-zA-Z0-9]{10}$"; +const char* REG_NAME_PATTERN = "^[a-zA-Z0-9._-]{1,}$"; +const size_t PACKAGE_ID_LENGTH = 10; + +static const DPL::String SETTING_VALUE_ENCRYPTION = L"encryption"; +static const DPL::String SETTING_VALUE_ENCRYPTION_ENABLE = L"enable"; +static const DPL::String SETTING_VALUE_ENCRYPTION_DISABLE = L"disable"; +const DPL::String SETTING_VALUE_INSTALLTOEXT_NAME = L"install-location"; +const DPL::String SETTING_VALUE_INSTALLTOEXT_PREPER_EXT = L"prefer-external"; +const DPL::String SETTING_VALUE_INSTALLTOEXT_AUTO = L"auto"; +const std::string XML_EXTENSION = ".xml"; + +bool hasExtension(const std::string& filename, const std::string& extension) +{ + _D("Looking for extension %s in %s", extension.c_str(), filename.c_str()); + size_t fileLen = filename.length(); + size_t extLen = extension.length(); + if (fileLen < extLen) { + _E("Filename %s is shorter than extension %s", filename.c_str(), extension.c_str()); + return false; + } + return (0 == filename.compare(fileLen - extLen, extLen, extension)); +} +} // namespace anonymous + +namespace Jobs { +namespace WidgetInstall { + +TaskConfiguration::TaskConfiguration(InstallerContext& context) : + DPL::TaskDecl(this), + m_context(context), + m_widgetConfig(m_context.widgetConfig.configInfo) +{ + AddStep(&TaskConfiguration::StartStep); + + AddStep(&TaskConfiguration::SetupTempDirStep); + AddStep(&TaskConfiguration::UnzipConfigurationStep); + AddStep(&TaskConfiguration::ParseXMLConfigStep); + + AddStep(&TaskConfiguration::TizenIdStep); + AddStep(&TaskConfiguration::CheckAppRunningStateStep); + AddStep(&TaskConfiguration::ApplicationTypeStep); + AddStep(&TaskConfiguration::ResourceEncryptionStep); + AddStep(&TaskConfiguration::InstallationFSLocationStep); + + AddStep(&TaskConfiguration::DetectUpdateInstallationStep); + AddStep(&TaskConfiguration::CheckRDSSupportStep); + AddStep(&TaskConfiguration::ConfigureWidgetLocationStep); + AddStep(&TaskConfiguration::PkgmgrStartStep); + + AddStep(&TaskConfiguration::AppendTasklistStep); + + AddStep(&TaskConfiguration::EndStep); +} + +void TaskConfiguration::StartStep() +{ + _D("--------- : START ----------"); +} + +void TaskConfiguration::EndStep() +{ + m_context.job->UpdateProgress(InstallerContext::INSTALL_PARSE_CONFIG, + "Parse config.xml and set structure"); + _D("--------- : END ----------"); +} + +void TaskConfiguration::PkgmgrStartStep() +{ + pkgMgrInterface()->sendProgress(0); +} + +void TaskConfiguration::AppendTasklistStep() +{ + if (!m_context.isUpdateMode) { + _D("TaskConfiguration -> new installation task list"); + m_context.job->appendNewInstallationTaskList(); + } else { + _D("TaskConfiguration -> update installation task list"); + m_context.job->appendUpdateInstallationTaskList(); + } +} + +std::shared_ptr TaskConfiguration::pkgMgrInterface() +{ + return m_context.job->GetInstallerStruct().pkgmgrInterface; +} + +void TaskConfiguration::SetupTempDirStep() +{ + _D("widgetPath: %s", m_context.requestedPath.c_str()); + _D("tempPath: %s", m_tempDir.c_str()); + if (m_context.mode.extension == InstallMode::ExtensionType::DIR) { + if (m_context.mode.command == + InstallMode::Command::REINSTALL) { + std::ostringstream tempPathBuilder; + tempPathBuilder << WrtDB::GlobalConfig::GetUserInstalledWidgetPath(); + tempPathBuilder << WrtDB::GlobalConfig::GetTmpDirPath(); + tempPathBuilder << "/"; + tempPathBuilder << m_context.requestedPath; + m_tempDir = tempPathBuilder.str(); + } else { + m_tempDir = m_context.requestedPath; + } + } else { + m_tempDir = + Jobs::WidgetInstall::createTempPath( + m_context.mode.rootPath == + InstallMode::RootPath::RO); + } +} + +void TaskConfiguration::UnzipConfigurationStep() +{ + _D("UnzipConfigurationStep"); + if (m_context.mode.extension != InstallMode::ExtensionType::DIR) { + if(!hasExtension(m_context.requestedPath, XML_EXTENSION)) //unzip everything except xml files + { + WidgetUnzip wgtUnzip(m_context.requestedPath); + wgtUnzip.unzipConfiguration(m_tempDir, &m_context.widgetConfig.packagingType); + m_configuration += m_tempDir + "/" + CONFIG_XML; + } else{ + m_context.widgetConfig.packagingType = PKG_TYPE_HOSTED_WEB_APP; + m_configuration += m_context.requestedPath; + } + } else { + if (m_context.mode.command == InstallMode::Command::REINSTALL) { + std::string configFile = m_tempDir + "/" + CONFIG_XML; + if (!WrtUtilFileExists(configFile)) { + configFile = m_tempDir + "/" + WITH_OSP_XML; + if (!WrtUtilFileExists(configFile)) { + std::string tzAppId = m_context.requestedPath. + substr(m_context.requestedPath.find_last_of("/")+1); + WidgetDAOReadOnly dao(WidgetDAOReadOnly::getTzAppId( + DPL::FromUTF8String(tzAppId))); + configFile = DPL::ToUTF8String(*dao.getWidgetInstalledPath()); + configFile += "/"; + configFile += WITH_OSP_XML; + } + } else { + m_context.widgetConfig.packagingType = PKG_TYPE_NOMAL_WEB_APP; + } + m_configuration = configFile; + } else { + m_configuration = m_tempDir + "/" + WITH_OSP_XML; + } + } + _D("m_configuration : %s", m_configuration.c_str()); + _D("Package Type : %s", m_context.widgetConfig.packagingType.getPkgtypeToString().c_str()); +} + +void TaskConfiguration::ParseXMLConfigStep() +{ + _D("ParseXMLConfigStep"); + // Parse config + ParserRunner parser; + Try + { + if(!DPL::Utils::Path(m_configuration).Exists()) + { + ThrowMsg(Exceptions::MissingConfig, "Config file not exists"); + } + +#ifdef SCHEMA_VALIDATION_ENABLED + if(!parser.Validate(configFilePath, WRT_WIDGETS_XML_SCHEMA)) + { + _E("Invalid configuration file - schema validation failed"); + ThrowMsg(Exceptions::WidgetConfigFileInvalid, "Failed to parse config.xml file"); + } +#endif + parser.Parse(m_configuration, + ElementParserPtr( + new RootParser(m_widgetConfig, + DPL:: + FromUTF32String( + L"widget")))); + } + Catch(ElementParser::Exception::ParseError) + { + _E("Failed to parse config.xml file"); + ThrowMsg(Exceptions::WidgetConfigFileInvalid, "Parser exeption"); + } + Catch(WidgetDAOReadOnly::Exception::WidgetNotExist) + { + _E("Failed to find installed widget - give proper tizenId"); + ThrowMsg(Exceptions::RDSDeltaFailure, "WidgetNotExist"); + } + Catch(Exceptions::WidgetConfigFileNotFound){ + _E("Failed to find config.xml"); + ThrowMsg(Exceptions::MissingConfig, "Parser exeption"); + } + + if (!WrtUtilRemove(m_configuration)) { + _E("Error occurs during removing %s", m_configuration.c_str()); + } + +} + +void TaskConfiguration::TizenIdStep() +{ + bool shouldMakeAppid = false; + using namespace PackageManager; + + if (!!m_widgetConfig.tizenAppId) { + _D("Setting tizenAppId provided in config.xml: %s", DPL::ToUTF8String(*m_widgetConfig.tizenAppId).c_str()); + + m_context.widgetConfig.tzAppid = *m_widgetConfig.tizenAppId; + //check package id. + if (!!m_widgetConfig.tizenPkgId) { + _D("Setting tizenPkgId provided in config.xml: %s", DPL::ToUTF8String(*m_widgetConfig.tizenPkgId).c_str()); + + m_context.widgetConfig.tzPkgid = *m_widgetConfig.tizenPkgId; + } else { + DPL::String appid = *m_widgetConfig.tizenAppId; + if (appid.length() > PACKAGE_ID_LENGTH) { + m_context.widgetConfig.tzPkgid = + appid.substr(0, PACKAGE_ID_LENGTH); + } else { + //old version appid only has 10byte random character is able to install for a while. + //this case appid equal pkgid. + m_context.widgetConfig.tzPkgid = + *m_widgetConfig.tizenAppId; + shouldMakeAppid = true; + } + } + } else { + shouldMakeAppid = true; + TizenPkgId pkgId = WidgetDAOReadOnly::generatePkgId(); + _D("Checking if pkg id is unique"); + while (true) { + if (!validateTizenPackageID(pkgId)) { + //path exist, chose another one + pkgId = WidgetDAOReadOnly::generatePkgId(); + continue; + } + break; + } + m_context.widgetConfig.tzPkgid = pkgId; + _D("tizen_id name was generated by WRT: %ls", m_context.widgetConfig.tzPkgid.c_str()); + } + + if (shouldMakeAppid == true) { + DPL::OptionalString name; + DPL::OptionalString defaultLocale = m_widgetConfig.defaultlocale; + + FOREACH(localizedData, m_widgetConfig.localizedDataSet) + { + Locale i = localizedData->first; + if (!!defaultLocale) { + if (defaultLocale == i) { + name = localizedData->second.name; + break; + } + } else { + name = localizedData->second.name; + break; + } + } + regex_t regx; + if (regcomp(®x, REG_NAME_PATTERN, REG_NOSUB | REG_EXTENDED) != 0) { + _D("Regcomp failed"); + } + + _D("Name : %ls", (*name).c_str()); + if (!name || (regexec(®x, DPL::ToUTF8String(*name).c_str(), + static_cast(0), NULL, 0) != REG_NOERROR)) + { + const std::string allowedString("ABCDEFGHIJKLMNOPQRSTUVWXYZ"); + std::ostringstream genName; + struct timeval tv; + gettimeofday(&tv, NULL); + unsigned int seed = time(NULL) + tv.tv_usec; + + genName << "_" << allowedString[rand_r(&seed) % allowedString.length()]; + name = DPL::FromUTF8String(genName.str()); + _D("name was generated by WRT"); + } + regfree(®x); + _D("Name : %ls", (*name).c_str()); + std::ostringstream genid; + genid << m_context.widgetConfig.tzPkgid << "." << name; + _D("tizen appid was generated by WRT : %s", genid.str().c_str()); + + DPL::OptionalString appid = DPL::FromUTF8String(genid.str()); + NormalizeAndTrimSpaceString(appid); + m_context.widgetConfig.tzAppid = *appid; + } + + // send start signal of pkgmgr + pkgMgrInterface()->setPkgname(DPL::ToUTF8String(m_context.widgetConfig.tzPkgid)); + + _D("Tizen App Id : %ls", (m_context.widgetConfig.tzAppid).c_str()); + _D("Tizen Pkg Id : %ls", (m_context.widgetConfig.tzPkgid).c_str()); +} + +void TaskConfiguration::CheckAppRunningStateStep() +{ + bool isRunning = false; + int ret = + app_manager_is_running(DPL::ToUTF8String(m_context.widgetConfig.tzAppid).c_str(), + &isRunning); + if (APP_MANAGER_ERROR_NONE != ret) { + _E("Fail to get running state"); + ThrowMsg(Jobs::WidgetInstall::Exceptions::WidgetRunningError, + "widget is running"); + } + + if (true == isRunning) { + // get app_context for running application + // app_context must be released with app_context_destroy + app_context_h appCtx = NULL; + ret = + app_manager_get_app_context( + DPL::ToUTF8String(m_context.widgetConfig.tzAppid).c_str(), + &appCtx); + if (APP_MANAGER_ERROR_NONE != ret) { + _E("Fail to get app_context"); + ThrowMsg(Jobs::WidgetInstall::Exceptions::WidgetRunningError, + "widget is running"); + } + + // terminate app_context_h + ret = app_manager_terminate_app(appCtx); + if (APP_MANAGER_ERROR_NONE != ret) { + _E("Fail to terminate running application"); + app_context_destroy(appCtx); + ThrowMsg(Jobs::WidgetInstall::Exceptions::WidgetRunningError, + "widget is running"); + } else { + app_context_destroy(appCtx); + // app_manager_terminate_app isn't sync API + // wait until application isn't running (50ms * 100) + bool isStillRunning = true; + int checkingloop = 100; + struct timespec duration = { 0, 50 * 1000 * 1000 }; + while (--checkingloop >= 0) { + nanosleep(&duration, NULL); + int ret = app_manager_is_running( + DPL::ToUTF8String(m_context.widgetConfig.tzAppid).c_str(), + &isStillRunning); + if (APP_MANAGER_ERROR_NONE != ret) { + _E("Fail to get running state"); + ThrowMsg(Jobs::WidgetInstall::Exceptions::WidgetRunningError, + "widget is running"); + } + if (!isStillRunning) { + break; + } + } + if (isStillRunning) { + _E("Fail to terminate running application"); + ThrowMsg(Jobs::WidgetInstall::Exceptions::WidgetRunningError, + "widget is running"); + } + _D("terminate application"); + } + } +} + +void TaskConfiguration::ConfigureWidgetLocationStep() +{ + m_context.locations = + WidgetLocation(DPL::ToUTF8String(m_context.widgetConfig.tzPkgid), + m_context.requestedPath, m_tempDir, + m_context.widgetConfig.packagingType, + m_context.mode.rootPath == + InstallMode::RootPath::RO, + m_context.mode.extension); + m_context.locations->registerAppid( + DPL::ToUTF8String(m_context.widgetConfig.tzAppid)); + + _D("widgetSource %s", m_context.requestedPath.c_str()); +} + +void TaskConfiguration::DetectUpdateInstallationStep() +{ + WidgetUpdateInfo update; + // checking installed web application + Try { + // no excpetion means, it isn't update mode + update = detectWidgetUpdate(m_widgetConfig, + m_context.widgetConfig.tzAppid); + checkWidgetUpdate(update); + + m_context.isUpdateMode = true; + + //if update, notify pkgmgr that this is update + pkgMgrInterface()->startJob(InstallationType::UpdateInstallation); + } + Catch(WidgetDAOReadOnly::Exception::WidgetNotExist) { + pkgMgrInterface()->startJob(InstallationType::NewInstallation); + + m_context.isUpdateMode = false; + + if (!validateTizenApplicationID( + m_context.widgetConfig.tzAppid)) + { + _E("tizen application ID is already used"); + ThrowMsg(Jobs::WidgetInstall::Exceptions::WidgetConfigFileInvalid, + "invalid config"); + } + if (!validateTizenPackageID(m_context.widgetConfig.tzPkgid)) { + _E("tizen package ID is already used"); + ThrowMsg(Jobs::WidgetInstall::Exceptions::PackageAlreadyInstalled, + "package is already installed"); + } + } +} + +void TaskConfiguration::CheckRDSSupportStep() +{ + //update needs RDS support to go ahead if REINSTALL command is given + if(m_context.isUpdateMode) + { + if (!checkSupportRDSUpdateIfReinstall(m_widgetConfig)) { + ThrowMsg(Jobs::WidgetInstall::Exceptions::NotSupportRDSUpdate, + "RDS update failed"); + } + } +} + +bool TaskConfiguration::validateTizenApplicationID( + const WrtDB::TizenAppId &tizenAppId) +{ + _D("tizen application ID = [%ls]", tizenAppId.c_str()); + + regex_t reg; + if (regcomp(®, REG_TIZENID_PATTERN, REG_NOSUB | REG_EXTENDED) != 0) { + _D("Regcomp failed"); + return false; + } + + if (regexec(®, DPL::ToUTF8String(tizenAppId).c_str(), 0, NULL, 0) + == REG_NOMATCH) + { + regfree(®); + return false; + } + regfree(®); + return true; +} + +bool TaskConfiguration::validateTizenPackageID( + const WrtDB::TizenPkgId &tizenPkgId) +{ + _D("tizen application ID = [%ls]", tizenPkgId.c_str()); + + regex_t reg; + if (regcomp(®, REG_PKGID_PATTERN, REG_NOSUB | REG_EXTENDED) != 0) + { + _D("Regcomp failed"); + return false; + } + if (regexec(®, DPL::ToUTF8String(tizenPkgId).c_str(), 0, NULL, 0) == REG_NOMATCH) + { + regfree(®); + return false; + } + regfree(®); + return true; +} + +bool TaskConfiguration::checkWidgetUpdate( + const WidgetUpdateInfo &update) +{ + if (update.existingVersion.IsNull() || update.incomingVersion.IsNull()) { + return false; + } + + _D("existing version = '%ls", update.existingVersion->Raw().c_str()); + _D("incoming version = '%ls", update.incomingVersion->Raw().c_str()); + _D("Tizen AppID = %ls", update.tzAppId.c_str()); + + m_context.widgetConfig.tzAppid = update.tzAppId; + + if (!!update.existingVersion || + m_context.mode.extension == + InstallMode::ExtensionType::DIR) { + return true; + } + + return false; +} + +WidgetUpdateInfo TaskConfiguration::detectWidgetUpdate( + const ConfigParserData &configInfo, + const WrtDB::TizenAppId &tizenId) +{ + _D("Checking up widget package for config.xml..."); + OptionalWidgetVersion incomingVersion; + + if (!configInfo.version.IsNull()) { + incomingVersion = + DPL::Optional( + WidgetVersion(*configInfo.version)); + } + + WidgetDAOReadOnly dao(tizenId); + + OptionalWidgetVersion optVersion; + DPL::OptionalString version = dao.getVersion(); + if (!version.IsNull()) { + optVersion = OptionalWidgetVersion(WidgetVersion(*version)); + } + + return WidgetUpdateInfo( + dao.getTzAppId(), + optVersion, + incomingVersion); +} + +void TaskConfiguration::ApplicationTypeStep() //TODO: is this really needed as WAC is not supported? +{ + AppType widgetAppType = APP_TYPE_UNKNOWN; + FOREACH(iterator, m_widgetConfig.nameSpaces) { + _D("namespace = [%ls]", (*iterator).c_str()); + + if (*iterator == ConfigurationNamespace::TizenWebAppNamespaceName) { + widgetAppType = APP_TYPE_TIZENWEBAPP; + break; + } + } + + m_context.widgetConfig.webAppType = widgetAppType; + + _D("type = [%s]", m_context.widgetConfig.webAppType.getApptypeToString().c_str()); +} + +void TaskConfiguration::ResourceEncryptionStep() +{ + m_context.needEncryption = false; + FOREACH(it, m_widgetConfig.settingsList) + { + if (it->m_name == SETTING_VALUE_ENCRYPTION && + it->m_value == SETTING_VALUE_ENCRYPTION_ENABLE) + { + _D("resource need encryption"); + m_context.needEncryption = true; + } + } +} + +void TaskConfiguration::InstallationFSLocationStep() +{ + if (m_context.mode.installTime != InstallMode::InstallTime::PRELOAD) { + FOREACH(it, m_widgetConfig.settingsList) { + if (it->m_name == SETTING_VALUE_INSTALLTOEXT_NAME) { + if (it->m_value == SETTING_VALUE_INSTALLTOEXT_AUTO) { + m_context.locationType = INSTALL_LOCATION_TYPE_AUTO; + } else if (it->m_value == SETTING_VALUE_INSTALLTOEXT_PREPER_EXT) { + m_context.locationType = + INSTALL_LOCATION_TYPE_PREFER_EXTERNAL; + } else { + m_context.locationType = + INSTALL_LOCATION_TYPE_INTERNAL_ONLY; + } + break; + } + } + } +} + +bool TaskConfiguration::checkSupportRDSUpdateIfReinstall(const WrtDB::ConfigParserData + &configInfo) +{ + if (m_context.mode.command == + InstallMode::Command::REINSTALL) + { + DPL::String configValue = SETTING_VALUE_ENCRYPTION_DISABLE; + DPL::String dbValue = SETTING_VALUE_ENCRYPTION_DISABLE; + + WidgetDAOReadOnly dao(m_context.widgetConfig.tzAppid); + WrtDB::WidgetSettings widgetSettings; + dao.getWidgetSettings(widgetSettings); + + FOREACH(it, widgetSettings) { + if (it->settingName == SETTING_VALUE_ENCRYPTION) { + dbValue = it->settingValue; + } + } + + FOREACH(data, configInfo.settingsList) + { + if (data->m_name == SETTING_VALUE_ENCRYPTION) + { + configValue = data->m_value; + } + } + if (configValue != dbValue) { + _E("Not Support RDS mode because of encryption setting"); + return false; + } + } + + return true; +} + +} +} diff --git a/src_mobile/jobs/widget_install/task_configuration.h b/src_mobile/jobs/widget_install/task_configuration.h new file mode 100644 index 0000000..39e4701 --- /dev/null +++ b/src_mobile/jobs/widget_install/task_configuration.h @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file task_configuration.h + * @version 1.0 + * @author Tomasz Iwanek + * @brief header file for configuration task + */ +#ifndef TASK_CONFIGURATION_H +#define TASK_CONFIGURATION_H + +#include + +#include +#include + +#include +#include + +#include + +class InstallerContext; + +namespace Jobs { +namespace WidgetInstall { + +class TaskConfiguration : public DPL::TaskDecl +{ + InstallerContext& m_context; + std::string m_tempDir; + WrtDB::ConfigParserData &m_widgetConfig; + std::string m_configuration; + + WidgetUpdateInfo m_widgetUpdateInfo; + + void parseWidgetXMLConfig( + const std::string &widgetSource, + const std::string &tempPath, + WrtDB::PackagingType pkgType, + bool isReinstall); + + static WidgetUpdateInfo detectWidgetUpdate( + const WrtDB::ConfigParserData &configInfo, + const WrtDB::TizenAppId &tizenId); + + bool validateTizenApplicationID(const WrtDB::TizenAppId &tizenAppId); + bool validateTizenPackageID(const WrtDB::TizenPkgId &tizenPkgId); + bool checkWidgetUpdate(const WidgetUpdateInfo &update); + void ApplicationTypeStep(const WrtDB::ConfigParserData &configInfo); + bool checkSupportRDSUpdateIfReinstall(const WrtDB::ConfigParserData &configInfo); + bool getDefaultExternalStorage(); + bool getMMCStatus(); + + std::shared_ptr pkgMgrInterface(); + + //steps + void StartStep(); + + void SetupTempDirStep(); + void UnzipConfigurationStep(); + void ParseXMLConfigStep(); + + void TizenIdStep(); + void CheckAppRunningStateStep(); + void DetectUpdateInstallationStep(); + void PkgmgrStartStep(); + + void ApplicationTypeStep(); + void ResourceEncryptionStep(); + void InstallationFSLocationStep(); + + void ConfigureWidgetLocationStep(); + void CheckRDSSupportStep(); + + void AppendTasklistStep(); + void EndStep(); + +public: + TaskConfiguration(InstallerContext& context); +}; + +} +} + +#endif // TASK_CONFIGURATION_H diff --git a/src_mobile/jobs/widget_install/task_database.cpp b/src_mobile/jobs/widget_install/task_database.cpp new file mode 100644 index 0000000..9dc4e15 --- /dev/null +++ b/src_mobile/jobs/widget_install/task_database.cpp @@ -0,0 +1,392 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file task_new_db_insert.cpp + * @author Lukasz Wrzosek(l.wrzosek@samsung.com) + * @author Soyoung kim(sy037.kim@samsung.com) + * @version 1.0 + * @brief Implementation file for installer task database updating for widget + * update + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace WrtDB; + +namespace Jobs { +namespace WidgetInstall { +TaskDatabase::TaskDatabase(InstallerContext& context) : + DPL::TaskDecl(this), + m_context(context), + m_handleToRemove(INVALID_WIDGET_HANDLE), + m_handle(INVALID_WIDGET_HANDLE) +{ + AddStep(&TaskDatabase::StartStep); + AddStep(&TaskDatabase::StepRegisterExternalFiles); + AddStep(&TaskDatabase::StepWrtDBInsert); + AddStep(&TaskDatabase::StepAceDBInsert); + AddStep(&TaskDatabase::StepSecurityOriginDBInsert); + AddStep(&TaskDatabase::StepWidgetInterfaceDBInsert); + AddStep(&TaskDatabase::StepRemoveExternalFiles); + AddStep(&TaskDatabase::StepLiveboxDBInsert); + AddStep(&TaskDatabase::EndStep); + + AddAbortStep(&TaskDatabase::StepAbortDBInsert); + AddAbortStep(&TaskDatabase::StepAbortAceDBInsert); + AddAbortStep(&TaskDatabase::StepAbortWidgetInterfaceDBInsert); +} + +void TaskDatabase::StepWrtDBInsert() +{ + Try + { + /* Set install Time */ + time(&m_context.widgetConfig.installedTime); + + if (m_context.isUpdateMode) { //update + _D("Registering widget... (update)"); + Try + { + m_handleToRemove = WidgetDAOReadOnly::getHandle( + m_context.widgetConfig.tzAppid); + + std::string makeAppid = + DPL::ToUTF8String(m_context.widgetConfig.tzAppid) + "." + + "backup"; + m_backAppId = DPL::FromUTF8String(makeAppid); + } + Catch(WidgetDAOReadOnly::Exception::WidgetNotExist) + { + _E("Given tizenId not found for update installation (Same GUID?)"); + ThrowMsg(Exceptions::DatabaseFailure, + "Given tizenId not found for update installation"); + } + + WidgetDAO::updateTizenAppId(m_context.widgetConfig.tzAppid, + m_backAppId); + WidgetDAO::registerWidget(m_context.widgetConfig.tzAppid, + m_context.widgetConfig, + m_context.widgetSecurity); + m_handle = + WidgetDAOReadOnly::getHandle(m_context.widgetConfig.tzAppid); + } else { //new installation + _D("Registering widget..."); + WidgetDAO::registerWidget( + m_context.widgetConfig.tzAppid, + m_context.widgetConfig, + m_context.widgetSecurity); + m_handle = WidgetDAOReadOnly::getHandle( + m_context.widgetConfig.tzAppid); + } + + FOREACH(cap, m_context.staticPermittedDevCaps) { + _D("staticPermittedDevCaps : %ls smack status: %d", cap->first.c_str(), cap->second); + } + + _D("Widget registered"); + } + Catch(WidgetDAO::Exception::DatabaseError) + { + _E("Database failure!"); + ReThrowMsg(Exceptions::InsertNewWidgetFailed, "Database failure!"); + } + Catch(DPL::DB::SqlConnection::Exception::Base) + { + _E("Database failure!"); + ReThrowMsg(Exceptions::InsertNewWidgetFailed, "Database failure!"); + } +} + +void TaskDatabase::StepAceDBInsert() +{ + _D("Inserting Ace database entry. New handle: %d", m_handle); + if (INVALID_WIDGET_HANDLE != m_handleToRemove) { + _D("Removing old insallation. Handle: %d", m_handleToRemove); + if (ACE_OK != ace_unregister_widget( + static_cast(m_handleToRemove))) + { + _W("Error while removing ace entry for previous insallation"); + } + } + + if (!AceApi::registerAceWidget(m_handle, m_context.widgetConfig, + m_context.widgetSecurity.getCertificateList())) + { + _E("ace database insert failed"); + ThrowMsg(Exceptions::UpdateFailed, + "Update failure. ace_register_widget failed"); + } + _D("Ace data inserted"); +} + +void TaskDatabase::StepSecurityOriginDBInsert() +{ + _D("Create Security origin database"); + // automatically create security origin database + using namespace SecurityOriginDB; + using namespace WrtDB; + + SecurityOriginDAO dao(m_context.locations->getPkgId()); + + // Checking privilege list for setting security origin exception data + FOREACH(it, m_context.widgetConfig.configInfo.privilegeList) { + std::map::const_iterator result = + g_W3CPrivilegeTextMap.find(DPL::ToUTF8String(it->name)); + if (result != g_W3CPrivilegeTextMap.end()) { + if (result->second == FEATURE_USER_MEDIA) { + dao.setPrivilegeSecurityOriginData(result->second, false); + } else if (result->second == FEATURE_FULLSCREEN_MODE) { + continue; + } else { + dao.setPrivilegeSecurityOriginData(result->second); + } + } + } +} + +void TaskDatabase::StepWidgetInterfaceDBInsert() +{ + _D("Create Widget Interface database"); + using namespace WidgetInterfaceDB; + using namespace WrtDB; + + DbWidgetHandle handle = + WidgetDAOReadOnly::getHandle(m_context.widgetConfig.tzAppid); + + // backup database + if (m_context.isUpdateMode) { + std::string dbPath = WidgetInterfaceDAO::databaseFileName(handle); + std::string backupDbPath = dbPath; + backupDbPath += GlobalConfig::GetBackupDatabaseSuffix(); + _D("\"%s\" to \"%s\"", dbPath.c_str(), backupDbPath.c_str()); + if (0 != std::rename(dbPath.c_str(), backupDbPath.c_str())) { + _E("widget interface database backup failed"); + ThrowMsg(Exceptions::UpdateFailed, + "widget interface database backup failed"); + } + } + + Try + { + // automatically create widget interface database + WidgetInterfaceDAO dao(handle); + } + Catch(WidgetInterfaceDAO::Exception::DatabaseError) + { + _E("widget interface database create failed"); + ThrowMsg(Exceptions::UpdateFailed, + "widget interface database create failed"); + } +} + +void TaskDatabase::StepRegisterExternalFiles() +{ + WrtDB::ExternalLocationList externalLocationsUpdate = + m_context.locations->listExternalLocations(); + if (m_context.isUpdateMode) { //update + Try + { + WidgetDAO dao(m_context.widgetConfig.tzAppid); + WrtDB::ExternalLocationList externalLocationsDB = + dao.getWidgetExternalLocations(); + FOREACH(file, externalLocationsDB) + { + if (std::find(externalLocationsUpdate.begin(), + externalLocationsUpdate.end(), + *file) == externalLocationsUpdate.end()) + { + m_externalLocationsToRemove.push_back(*file); + } + } + } + Catch(WidgetDAOReadOnly::Exception::WidgetNotExist) + { + _E("Given tizenId not found for update installation (Same GUID?)"); + ThrowMsg(Exceptions::UpdateFailed, + "Given tizenId not found for update installation"); + } + } + _D("Registering external files:"); + FOREACH(file, externalLocationsUpdate) + { + _D(" -> %s", (*file).c_str()); + } + + //set external locations to be registered + m_context.widgetConfig.externalLocations = externalLocationsUpdate; +} + +void TaskDatabase::StepRemoveExternalFiles() +{ + if (!m_externalLocationsToRemove.empty()) { + _D("Removing external files:"); + } + + FOREACH(file, m_externalLocationsToRemove) + { + if (WrtUtilFileExists(*file)) { + _D(" -> %s", (*file).c_str()); + if (-1 == TEMP_FAILURE_RETRY(remove(file->c_str()))) { + ThrowMsg(Exceptions::RemovingFileFailure, + "Failed to remove external file"); + } + } else if (WrtUtilDirExists(*file)) { + _D(" -> %s", (*file).c_str()); + if (!WrtUtilRemove(*file)) { + ThrowMsg(Exceptions::RemovingFolderFailure, + "Failed to remove external directory"); + } + } else { + _W(" -> %s(no such a path)", (*file).c_str()); + } + } +} + +void TaskDatabase::StepAbortDBInsert() +{ + _W("[DB Update Task] Aborting... (DB Clean)"); + Try + { + if (m_context.isUpdateMode) { + WidgetDAO::unregisterWidget(m_context.widgetConfig.tzAppid); + WidgetDAO::updateTizenAppId(m_backAppId, + m_context.widgetConfig.tzAppid); + } else { + WidgetDAO::unregisterWidget(m_context.widgetConfig.tzAppid); + } + _D("Cleaning DB successful!"); + } + Catch(DPL::DB::SqlConnection::Exception::Base) + { + _E("Failed to handle StepAbortDBClean!"); + } +} + +void TaskDatabase::StepAbortAceDBInsert() +{ + _W("[DB Update Task] ACE DB Aborting... (DB Clean)"); + + ace_unregister_widget(static_cast(m_handle)); + // Remove also old one. If it was already updated nothing wrong will happen, + // but if not old widget will be removed. + if (INVALID_WIDGET_HANDLE != m_handleToRemove) { + ace_unregister_widget(static_cast(m_handle)); + } + + if (!AceApi::registerAceWidgetFromDB(m_handleToRemove)) + { + _E("ace database restore failed"); + } + _D("Ace data inserted"); +} + +void TaskDatabase::StepAbortWidgetInterfaceDBInsert() +{ + _D("[DB Update Task] Widget interface Aborting..."); + using namespace WidgetInterfaceDB; + using namespace WrtDB; + + DbWidgetHandle handle = + WidgetDAOReadOnly::getHandle(m_context.widgetConfig.tzAppid); + std::string dbPath = WidgetInterfaceDAO::databaseFileName(handle); + + // remove database + if (remove(dbPath.c_str()) != 0) { + _W("Fail to remove"); + } + + // rollback database + if (m_context.isUpdateMode) { + std::string backupDbPath = dbPath; + backupDbPath += GlobalConfig::GetBackupDatabaseSuffix(); + _D("\"%s\" to \"%s\"", dbPath.c_str(), backupDbPath.c_str()); + if (0 != std::rename(backupDbPath.c_str(), dbPath.c_str())) { + _W("Fail to rollback"); + } + } +} + +void TaskDatabase::StepLiveboxDBInsert() +{ + if (m_context.widgetConfig.configInfo.m_livebox.size() <= 0) { + return; + } + + std::string tizenId = DPL::ToUTF8String(m_context.widgetConfig.tzAppid); + + // insert specific information to web livebox db + for (auto it = m_context.widgetConfig.configInfo.m_livebox.begin(); + it != m_context.widgetConfig.configInfo.m_livebox.end(); ++it) + { + std::string boxId = DPL::ToUTF8String((**it).m_liveboxId); + std::string boxType; + if ((**it).m_type.empty()) { + boxType = web_provider_livebox_get_default_type(); + } else { + boxType = DPL::ToUTF8String((**it).m_type); + } + _D("livebox id: %s", boxId.c_str()); + _D("livebox type: %s", boxType.c_str()); + + int autoLaunch = (**it).m_autoLaunch == L"true" ? 1 : 0; + _D("livebox auto-launch: %d", autoLaunch); + + int mouseEvent = (**it).m_boxInfo.m_boxMouseEvent == L"true" ? 1 : 0; + _D("livebox mouse-event: %d", mouseEvent); + + int pdFastOpen = (**it).m_boxInfo.m_pdFastOpen == L"true" ? 1 : 0; + _D("livebox pd fast-open: %d", pdFastOpen); + + web_provider_livebox_insert_box_info( + boxId.c_str(), tizenId.c_str(), boxType.c_str(), + autoLaunch, mouseEvent, pdFastOpen); + } +} + +void TaskDatabase::StartStep() +{ + _D("--------- : START ----------"); +} + +void TaskDatabase::EndStep() +{ + _D("--------- : END ----------"); +} +} //namespace WidgetInstall +} //namespace Jobs diff --git a/src_mobile/jobs/widget_install/task_database.h b/src_mobile/jobs/widget_install/task_database.h new file mode 100644 index 0000000..1291c36 --- /dev/null +++ b/src_mobile/jobs/widget_install/task_database.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file task_database.h + * @author Lukasz Wrzosek(l.wrzosek@samsung.com) + * @author Soyoung kim(sy037.kim@samsung.com) + * @version 1.0 + * @brief Header file for installer task database updating + */ +#ifndef INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_DATABASE_H +#define INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_DATABASE_H + +#include +#include + +#include + +class InstallerContext; + +namespace Jobs { +namespace WidgetInstall { +class TaskDatabase : + public DPL::TaskDecl +{ + private: + InstallerContext& m_context; + WrtDB::ExternalLocationList m_externalLocationsToRemove; + + //TODO: temporary needed until security-server start to use pkgName instead + //of widget handle + WrtDB::DbWidgetHandle m_handleToRemove; + WrtDB::DbWidgetHandle m_handle; + WrtDB::TizenAppId m_backAppId; + + void StepRegisterExternalFiles(); + void StepWrtDBInsert(); + void StepAceDBInsert(); + void StepSecurityOriginDBInsert(); + void StepWidgetInterfaceDBInsert(); + void StepRemoveExternalFiles(); + void StepLiveboxDBInsert(); + + void StepAbortDBInsert(); + void StepAbortAceDBInsert(); + void StepAbortWidgetInterfaceDBInsert(); + + void StartStep(); + void EndStep(); + + public: + TaskDatabase(InstallerContext& context); +}; +} //namespace WidgetInstall +} //namespace Jobs + +#endif // INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_DATABASE_H diff --git a/src_mobile/jobs/widget_install/task_encrypt_resource.cpp b/src_mobile/jobs/widget_install/task_encrypt_resource.cpp new file mode 100644 index 0000000..3966ca8 --- /dev/null +++ b/src_mobile/jobs/widget_install/task_encrypt_resource.cpp @@ -0,0 +1,349 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file task_ecnrypt_resource.cpp + * @author Soyoung Kim (sy037.kim@samsung.com) + * @version 1.0 + * @brief Implementation file for installer task encrypt resource + */ +#include "task_encrypt_resource.h" + +#undef __USE_FILE_OFFSET64 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +using namespace WrtDB; + +namespace { +const std::size_t ENCRYPTION_CHUNK_MAX_SIZE = 8192; // bytes +const std::size_t ENCRYPTION_DEC_CHUNK_SIZE = 4; // bytes + +std::set& getSupportedForEncryption() +{ + static std::set encryptSet; + if (encryptSet.empty()) { + encryptSet.insert(".html"); + encryptSet.insert(".htm"); + encryptSet.insert(".css"); + encryptSet.insert(".js"); + } + return encryptSet; +} + +bool isSupportedForEncryption(const std::string &file) +{ + size_t foundKey = file.rfind("."); + if (std::string::npos != foundKey) { + std::string mimeType = file.substr(foundKey); + std::transform(mimeType.begin(), mimeType.end(), mimeType.begin(), + ::tolower); + + return getSupportedForEncryption().count(mimeType) > 0; + } + return false; +} + +/** + * Opens a file. + * + * @param path Path to a file. + * @param mode Mode. + * @return Stream handle. + * @throw ExtractFileFailed If error (other than EINTR) occurs. + */ +FILE* openFile(const std::string& path, const std::string& mode) +{ + FILE* result = NULL; + + do + { + result = fopen(path.c_str(), mode.c_str()); + } while ((NULL == result) && (EINTR == errno)); + + if (NULL == result) + { + ThrowMsg(Jobs::WidgetInstall::Exceptions::EncryptionFailed, + "Could not open file " << path); + } + + return result; +} + +/** + * Reads bytes from a stream. + * + * @param buffer Buffer to read the bytes into. + * @param count Number of bytes to read. + * @param stream Stream to read from. + * @return Number of bytes read + * @throw ExtractFileFailed If error (other than EINTR) occurs. + */ +std::size_t readBytes(unsigned char* buffer, std::size_t count, FILE* stream) +{ + std::size_t result = std::fread(buffer, + sizeof(unsigned char), + count, + stream); + + if (result != count) + { + int error = errno; + if (0 != std::ferror(stream)) + { + if (EINTR != error) + { + ThrowMsg(Jobs::WidgetInstall::Exceptions::ErrorExternalInstallingFailure, + "Error while reading data" << + " [" << DPL::GetErrnoString(error) << "]"); + } + } + } + + return result; +} + +/** + * Writes bytes to a stream. + * + * @param buffer Data to write. + * @param count Number of bytes. + * @param stream Stream to write to. + * @throw ExtractFileFailed If error (other than EINTR) occurs. + */ +void writeBytes(unsigned char* buffer, std::size_t count, FILE* stream) +{ + std::size_t bytesWritten = 0; + std::size_t bytesToWrite = 0; + do + { + bytesToWrite = count - bytesWritten; + bytesWritten = std::fwrite(buffer + bytesWritten, + sizeof(unsigned char), + count - bytesWritten, + stream); + if ((bytesWritten != bytesToWrite) && (EINTR != errno)) + { + int error = errno; + ThrowMsg(Jobs::WidgetInstall::Exceptions::EncryptionFailed, + "Error while writing data" << + " [" << DPL::GetErrnoString(error) << "]"); + } + } while ((bytesWritten != bytesToWrite) && (EINTR == errno)); +} + +int ssmEncrypt(InstallMode::InstallTime time, std::string pkgId, const char* + inChunk, int inBytes, char** outChunk, int *outBytes) +{ + if (time == InstallMode::InstallTime::PRELOAD) { + return ssm_encrypt_preloaded_application(inChunk, inBytes, + outChunk, outBytes); + } else { + return ssm_encrypt(pkgId.c_str(), pkgId.length(), + inChunk, inBytes, + outChunk, outBytes); + } +} +} + +namespace Jobs { +namespace WidgetInstall { +TaskEncryptResource::TaskEncryptResource(InstallerContext& context) : + DPL::TaskDecl(this), + m_context(context) +{ + AddStep(&TaskEncryptResource::StartStep); + AddStep(&TaskEncryptResource::StepEncryptResource); + AddStep(&TaskEncryptResource::EndStep); +} + +void TaskEncryptResource::StepEncryptResource() +{ + _D("Step Encrypt resource"); + + EncryptDirectory(m_context.locations->getSourceDir()); +} + +void TaskEncryptResource::EncryptDirectory(std::string path) +{ + FTS *fts; + FTSENT *ftsent; + char * const paths[] = { const_cast(path.c_str()), NULL }; + + if ((fts = fts_open(paths, FTS_PHYSICAL | FTS_NOCHDIR, NULL)) == NULL) { + //ERROR + int error = errno; + _W("%s: fts_open failed with error: %s", __PRETTY_FUNCTION__, strerror(error)); + ThrowMsg(Exceptions::EncryptionFailed, "Error reading directory: " + << path); + } + + while ((ftsent = fts_read(fts)) != NULL) { + switch (ftsent->fts_info) { + case FTS_DP: + case FTS_DC: + case FTS_D: + case FTS_DEFAULT: + case FTS_SLNONE: + //directories, non-regular files, dangling symbolic links + break; + case FTS_F: + case FTS_NSOK: + case FTS_SL: + //regular files and other objects that can be counted + if (isSupportedForEncryption(ftsent->fts_path)) { + EncryptFile(ftsent->fts_path); + } + break; + case FTS_NS: + case FTS_DOT: + case FTS_DNR: + case FTS_ERR: + default: + _W("%s: traversal failed on file: %s with error: %s", __PRETTY_FUNCTION__, ftsent->fts_path, strerror(ftsent->fts_errno)); + ThrowMsg(Exceptions::EncryptionFailed, "Error reading file"); + break; + } + } + + if (fts_close(fts) == -1) { + int error = errno; + _W("%s: fts_close failed with error: %s", __PRETTY_FUNCTION__, strerror(error)); + } +} + +void TaskEncryptResource::EncryptFile(const std::string &fileName) +{ + _D("Encrypt file: %s", fileName.c_str()); + std::string encFile = fileName + ".enc"; + + struct stat info; + memset(&info, 0, sizeof(info)); + if (stat(fileName.c_str(), &info) != 0) + { + int error = errno; + ThrowMsg(Exceptions::EncryptionFailed, + "Could not access file " << fileName << + "[" << DPL::GetErrnoString(error) << "]"); + } + const std::size_t fileSize = info.st_size; + if (0 == fileSize) { + _D("%s size is 0, so encryption is skiped", fileName.c_str()); + return; + } + + // If update installed preload web, should skip encryption. + if (!(m_context.mode.rootPath == InstallMode::RootPath::RO && + m_context.mode.installTime == InstallMode::InstallTime::PRELOAD + && m_context.mode.extension == InstallMode::ExtensionType::DIR)) { + + DPL::ScopedFClose inFile(openFile(fileName, "r")); + DPL::ScopedFClose outFile(openFile(encFile, "w")); + + const std::size_t chunkSize = (fileSize > ENCRYPTION_CHUNK_MAX_SIZE + ? ENCRYPTION_CHUNK_MAX_SIZE : fileSize); + + std::unique_ptr inChunk(new unsigned char[chunkSize]); + std::size_t bytesRead = 0; + /* TODO : pkgId should change to appId after wrt-client label changed. */ + std::string pkgId = DPL::ToUTF8String(m_context.widgetConfig.tzPkgid); + + do + { + bytesRead = readBytes(inChunk.get(), chunkSize, inFile.Get()); + if (0 != bytesRead) { + int outDecSize = 0; + char *outChunk = NULL; + if (0 != ssmEncrypt(m_context.mode.installTime, pkgId, + (char*)inChunk.get(), (int)bytesRead, + &outChunk, &outDecSize)) { + ThrowMsg(Exceptions::EncryptionFailed, + "Encryption Failed using TrustZone"); + } + + std::stringstream toString; + toString << outDecSize; + + writeBytes((unsigned char*)toString.str().c_str(), + sizeof(int), outFile.Get()); + writeBytes((unsigned char*)outChunk, outDecSize, outFile.Get()); + delete outChunk; + } + inChunk.reset(new unsigned char[chunkSize]); + + } while (0 == std::feof(inFile.Get())); + + outFile.Reset(); + inFile.Reset(); + + _D("File encrypted successfully"); + _D("Remove plain-text file: %s", fileName.c_str()); + if (0 != unlink(fileName.c_str())) + { + Throw(Exceptions::EncryptionFailed); + } + + _D("Rename encrypted file"); + if (0 != std::rename(encFile.c_str(), fileName.c_str())) + { + Throw(Exceptions::EncryptionFailed); + } + } + + WrtDB::EncryptedFileInfo fileInfo; + fileInfo.fileName = DPL::FromUTF8String(fileName); + fileInfo.fileSize = fileSize; + + m_context.widgetConfig.encryptedFiles.insert(fileInfo); +} + +void TaskEncryptResource::StartStep() +{ + _D("--------- : START ----------"); +} + +void TaskEncryptResource::EndStep() +{ + m_context.job->UpdateProgress( + InstallerContext::INSTALL_ECRYPTION_FILES, + "Ecrypt resource files"); + + _D("--------- : END ----------"); +} +} //namespace WidgetInstall +} //namespace Jobs diff --git a/src_mobile/jobs/widget_install/task_encrypt_resource.h b/src_mobile/jobs/widget_install/task_encrypt_resource.h new file mode 100644 index 0000000..b89a992 --- /dev/null +++ b/src_mobile/jobs/widget_install/task_encrypt_resource.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file task_encrypt_resource.h + * @author soyoung kim (sy037.kim@samsung.com) + * @version 1.0 + */ + +#ifndef SRC_JOBS_WIDGET_INSTALL_TASK_RESOURCE_ENCRYPT_H_ +#define SRC_JOBS_WIDGET_INSTALL_TASK_RESOURCE_ENCRYPT_H_ + +#include +#include + +class InstallerContext; + +namespace Jobs { +namespace WidgetInstall { +class TaskEncryptResource : public DPL::TaskDecl +{ + private: + // Installation context + InstallerContext &m_context; + std::string tempInstalledPath; + + void StepEncryptResource(); + + void StartStep(); + void EndStep(); + + void EncryptDirectory(std::string path); + void EncryptFile(const std::string &fileName); + + public: + explicit TaskEncryptResource(InstallerContext &installerContext); +}; +} // namespace WidgetInstall +} // namespace Jobs +#endif /* SRC_JOBS_WIDGET_INSTALL_TASK_ENCRYPT_RESOURCE_H_ */ diff --git a/src_mobile/jobs/widget_install/task_file_manipulation.cpp b/src_mobile/jobs/widget_install/task_file_manipulation.cpp new file mode 100644 index 0000000..5e08d28 --- /dev/null +++ b/src_mobile/jobs/widget_install/task_file_manipulation.cpp @@ -0,0 +1,318 @@ +/* + * Copyright (c) 2010 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file task_db_update.cpp + * @author Lukasz Wrzosek(l.wrzosek@samsung.com) + * @version 1.0 + * @brief Implementation file for installer task database updating + */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define WEBAPP_DEFAULT_UID 5000 +#define WEBAPP_DEFAULT_GID 5000 + +namespace { +const mode_t PRIVATE_STORAGE_MODE = 0700; +const mode_t SHARED_STORAGE_MODE = 0755; +} + +using namespace WrtDB; + +namespace { +const char* GLIST_RES_DIR = "res"; + +bool _FolderCopy(std::string source, std::string dest) +{ + DIR* dir = opendir(source.c_str()); + if (NULL == dir) { + return false; + } + + struct dirent dEntry; + struct dirent *dEntryResult; + int return_code; + + do { + struct stat statInfo; + return_code = readdir_r(dir, &dEntry, &dEntryResult); + if (dEntryResult != NULL && return_code == 0) { + std::string fileName = dEntry.d_name; + std::string fullName = source + "/" + fileName; + + if (stat(fullName.c_str(), &statInfo) != 0) { + closedir(dir); + return false; + } + + if (S_ISDIR(statInfo.st_mode)) { + if (("." == fileName) || (".." == fileName)) { + continue; + } + std::string destFolder = dest + "/" + fileName; + WrtUtilMakeDir(destFolder); + + if (!_FolderCopy(fullName, destFolder)) { + closedir(dir); + return false; + } + } + + std::string destFile = dest + "/" + fileName; + std::ifstream infile(fullName); + std::ofstream outfile(destFile); + outfile << infile.rdbuf(); + outfile.close(); + infile.close(); + } + } while (dEntryResult != NULL && return_code == 0); + closedir(dir); + return true; +} +} + +namespace Jobs { +namespace WidgetInstall { +TaskFileManipulation::TaskFileManipulation(InstallerContext& context) : + DPL::TaskDecl(this), + m_context(context), + m_extHandle(NULL) +{ + AddStep(&TaskFileManipulation::StartStep); + AddStep(&TaskFileManipulation::StepCheckInstallLocation); + AddStep(&TaskFileManipulation::StepPrepareRootDirectory); + if (m_context.mode.extension != InstallMode::ExtensionType::DIR) + { + AddStep(&TaskFileManipulation::StepUnzipWgtFile); + } + AddStep(&TaskFileManipulation::EndStep); + + AddAbortStep(&TaskFileManipulation::StepAbortPrepareRootDirectory); +} + +void TaskFileManipulation::StepCheckInstallLocation() +{ + _D("StepCheckInstallLocation"); + if (m_context.mode.rootPath == InstallMode::RootPath::RO) { + m_context.locationType = INSTALL_LOCATION_TYPE_INTERNAL_ONLY; + return; + } + + std::string installedPath = WrtDB::GlobalConfig::GetUserInstalledWidgetPath(); + WidgetUnzip wgtUnzip(m_context.requestedPath); + + if (m_context.locationType == INSTALL_LOCATION_TYPE_AUTO) { + int storage = 0; + // vconf_get_int(VCONFKEY_SETAPPL_DEFAULT_MEM_INSTALL_APPLICATIONS_INT) + // 0 : phone internal memory + // 1 : SD card + if (vconf_get_int("db/setting/default_memory/download_application", + &storage)) { + _E("vconf_get_int(db/setting/default_memory/download_application) \ + failed."); + } + _D("default setting : storage [%d]", storage); + if (storage) { + m_context.locationType = INSTALL_LOCATION_TYPE_PREFER_EXTERNAL; + } else { + m_context.locationType = INSTALL_LOCATION_TYPE_INTERNAL_ONLY; + if(!wgtUnzip.checkAvailableSpace(installedPath)) { + m_context.locationType = INSTALL_LOCATION_TYPE_PREFER_EXTERNAL; + } + } + } + + if (m_context.locationType == INSTALL_LOCATION_TYPE_PREFER_EXTERNAL) { + int mmcStatus; + if (vconf_get_int(VCONFKEY_SYSMAN_MMC_STATUS, &mmcStatus)) { + _E("vconf_get_int(VCONFKEY_SYSMAN_MMC_STATUS) failed."); + mmcStatus = VCONFKEY_SYSMAN_MMC_INSERTED_NOT_MOUNTED; + } + + if (VCONFKEY_SYSMAN_MMC_MOUNTED != mmcStatus) { + _D("mmcStatus is MMC_REMOVED or NOT_MOUNTED."); + m_context.locationType = INSTALL_LOCATION_TYPE_INTERNAL_ONLY; + } + } + + if (m_context.locationType == INSTALL_LOCATION_TYPE_INTERNAL_ONLY) { + if(!wgtUnzip.checkAvailableSpace(installedPath)) { + ThrowMsg(Exceptions::OutOfStorageFailed, "There is no space for installation"); + } + } +} + +void TaskFileManipulation::StepPrepareRootDirectory() +{ + if (m_context.locationType == INSTALL_LOCATION_TYPE_PREFER_EXTERNAL) { + prepareExternalDir(); + } else { + std::string widgetPath = m_context.locations->getPackageInstallationDir(); + std::string widgetBinPath = m_context.locations->getBinaryDir(); + std::string widgetSrcPath = m_context.locations->getSourceDir(); + + WrtUtilMakeDir(widgetPath); + + _D("Create resource directory"); + WrtUtilMakeDir(widgetBinPath); + WrtUtilMakeDir(widgetSrcPath); + if (m_context.mode.installTime == InstallMode::InstallTime::PRELOAD) { + std::string userWidgetDir = m_context.locations->getUserDataRootDir(); + WrtUtilMakeDir(userWidgetDir); + } + } + + m_context.job->UpdateProgress( + InstallerContext::INSTALL_DIR_CREATE, + "Widget Directory Created"); +} + +void TaskFileManipulation::StepUnzipWgtFile() +{ + if (m_context.widgetConfig.packagingType != PKG_TYPE_HOSTED_WEB_APP) { + std::string instDir; + if (m_context.widgetConfig.packagingType == PKG_TYPE_HYBRID_WEB_APP) { + instDir = m_context.locations->getPackageInstallationDir(); + } else { + instDir = m_context.locations->getSourceDir(); + } + + _D("unzip file to %s", instDir.c_str()); + + WidgetUnzip wgtUnzip(m_context.requestedPath); + wgtUnzip.unzipWgtFile(instDir); + } else { + _D("From browser installation - unzip is not done"); + } + + m_context.job->UpdateProgress( + InstallerContext::INSTALL_UNZIP_WGT, + "Unzip Wgt file"); +} + +void TaskFileManipulation::StepAbortPrepareRootDirectory() +{ + _D("[Create Root Directory] Aborting.... (Rename path)"); + if (m_context.locationType == INSTALL_LOCATION_TYPE_PREFER_EXTERNAL) { + if (m_context.isUpdateMode) { + WidgetInstallToExtSingleton::Instance().postUpgrade(false); + } else { + WidgetInstallToExtSingleton::Instance().postInstallation(false); + } + WidgetInstallToExtSingleton::Instance().deinitialize(); + } else { + std::string widgetPath; + widgetPath = m_context.locations->getPackageInstallationDir(); + if (!WrtUtilRemove(widgetPath)) { + _E("Error occurs during removing existing folder"); + } + // Remove user data directory if preload web app. + std::string userData = m_context.locations->getUserDataRootDir(); + if (0 == access(userData.c_str(), F_OK)) { + if (!WrtUtilRemove(userData)) { + _E("Error occurs during removing user data directory"); + } + } + } +} + +void TaskFileManipulation::prepareExternalDir() +{ + _D("Step prepare to install in exernal directory"); + Try { + std::string pkgid = + DPL::ToUTF8String(m_context.widgetConfig.tzPkgid); + + WidgetInstallToExtSingleton::Instance().initialize(pkgid); + + std::unique_ptr zipFile(new + DPL::ZipInput(m_context.requestedPath)); + double unzipSize = zipFile->GetTotalUncompressedSize(); + int folderSize = (int)(unzipSize / (1024 * 1024)) + 1; + + GList *list = NULL; + app2ext_dir_details* dirDetail = NULL; + + dirDetail = (app2ext_dir_details*) calloc(1, + sizeof( + app2ext_dir_details)); + if (NULL == dirDetail) { + ThrowMsg(Exceptions::ErrorExternalInstallingFailure, + "error in app2ext"); + } + dirDetail->name = strdup(GLIST_RES_DIR); + dirDetail->type = APP2EXT_DIR_RO; + list = g_list_append(list, dirDetail); + + if (m_context.isUpdateMode) { + WidgetInstallToExtSingleton::Instance().preUpgrade(list, + folderSize); + } else { + WidgetInstallToExtSingleton::Instance().preInstallation(list, + folderSize); + } + free(dirDetail); + g_list_free(list); + + /* make bin directory */ + std::string widgetBinPath = m_context.locations->getBinaryDir(); + WrtUtilMakeDir(widgetBinPath); + std::string sourceDir = m_context.locations->getSourceDir(); + WrtUtilMakeDir(sourceDir); + } + Catch(DPL::ZipInput::Exception::OpenFailed) { + ReThrowMsg(Exceptions::ErrorExternalInstallingFailure, + "Error during \ + create external folder "); + } + Catch(WidgetInstallToExt::Exception::ErrorInstallToExt) + { + ReThrowMsg(Exceptions::ErrorExternalInstallingFailure, + "Error during create external folder "); + } +} + +void TaskFileManipulation::StartStep() +{ + _D("--------- : START ----------"); +} + +void TaskFileManipulation::EndStep() +{ + _D("--------- : END ----------"); +} +} //namespace WidgetInstall +} //namespace Jobs diff --git a/src_mobile/jobs/widget_install/task_file_manipulation.h b/src_mobile/jobs/widget_install/task_file_manipulation.h new file mode 100644 index 0000000..113ca72 --- /dev/null +++ b/src_mobile/jobs/widget_install/task_file_manipulation.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file task_db_update.h + * @author Lukasz Wrzosek(l.wrzosek@samsung.com) + * @version 1.0 + * @brief Header file for installer task database updating + */ +#ifndef INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_FILE_MANIPULATION_H +#define INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_FILE_MANIPULATION_UPDATE_H + +#include +#include + +class InstallerContext; + +namespace Jobs { +namespace WidgetInstall { +class TaskFileManipulation : + public DPL::TaskDecl +{ + InstallerContext& m_context; + app2ext_handle *m_extHandle; + + // install internal location + void StepCheckInstallLocation(); + void StepPrepareRootDirectory(); + void StepUnzipWgtFile(); + void StepAbortPrepareRootDirectory(); + void StepLinkForPreload(); + void StartStep(); + void EndStep(); + + // install external location + void prepareExternalDir(); + + public: + TaskFileManipulation(InstallerContext& context); +}; +} //namespace WidgetInstall +} //namespace Jobs + +#endif // INSTALLER_CORE_JOS_WIDGET_INSTALL_FILE_MANIPULATION_H diff --git a/src_mobile/jobs/widget_install/task_install_ospsvc.cpp b/src_mobile/jobs/widget_install/task_install_ospsvc.cpp new file mode 100644 index 0000000..15923f9 --- /dev/null +++ b/src_mobile/jobs/widget_install/task_install_ospsvc.cpp @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file task_install_ospsvc.cpp + * @author Soyoung Kim (sy037.kim@samsung.com) + * @version 1.0 + * @brief Implementation file for installer task install osp service + */ +#include "task_install_ospsvc.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +using namespace WrtDB; + +namespace { +const int MAX_BUF_SIZE = 128; +const char* OSP_INSTALL_STR1 = "/usr/etc/package-manager/backend/tpk -iv "; +const char* OSP_INSTALL_STR2 = " -p "; +} + +namespace Jobs { +namespace WidgetInstall { +TaskInstallOspsvc::TaskInstallOspsvc(InstallerContext& context) : + DPL::TaskDecl(this), + m_context(context) +{ + AddStep(&TaskInstallOspsvc::StartStep); + AddStep(&TaskInstallOspsvc::StepInstallOspService); + AddStep(&TaskInstallOspsvc::EndStep); +} + +void TaskInstallOspsvc::StepInstallOspService() +{ + _D("Step: installation for osp service"); + + std::ostringstream commStr; + commStr << OSP_INSTALL_STR1<< BashUtils::escape_arg( + m_context.locations->getPackageInstallationDir()) + << OSP_INSTALL_STR2 << m_context.certLevel; + _D("osp install command : %s", commStr.str().c_str()); + + char readBuf[MAX_BUF_SIZE]; + FILE *fd; + fd = popen(commStr.str().c_str(), "r"); + if (NULL == fd) { + _E("Failed to installtion osp service"); + ThrowMsg(Exceptions::InstallOspsvcFailed, + "Error occurs during\ + install osp service"); + } + + if (fgets(readBuf, MAX_BUF_SIZE, fd) == NULL) + { + _E("Failed to installtion osp service.\ + Inability of reading file."); + ThrowMsg(Exceptions::InstallOspsvcFailed, + "Error occurs during\ + install osp service"); + } + _D("return value : %s", readBuf); + + int result = atoi(readBuf); + if (0 != result) { + ThrowMsg(Exceptions::InstallOspsvcFailed, + "Error occurs during\ + install osp service"); + } + + pclose(fd); +} + +void TaskInstallOspsvc::StartStep() +{ + _D("--------- : START ----------"); +} + +void TaskInstallOspsvc::EndStep() +{ + m_context.job->UpdateProgress( + InstallerContext::INSTALL_INSTALL_OSPSVC, + "Installed Osp servcie"); + + _D("--------- : END ----------"); +} +} //namespace WidgetInstall +} //namespace Jobs diff --git a/src_mobile/jobs/widget_install/task_install_ospsvc.h b/src_mobile/jobs/widget_install/task_install_ospsvc.h new file mode 100644 index 0000000..3e3a7e6 --- /dev/null +++ b/src_mobile/jobs/widget_install/task_install_ospsvc.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file task_install_ospsvc.h + * @author soyoung kim (sy037.kim@samsung.com) + * @version 1.0 + */ + +#ifndef SRC_JOBS_WIDGET_INSTALL_TASK_INSTALL_OSPSVC_H_ +#define SRC_JOBS_WIDGET_INSTALL_TASK_INSTALL_OSPSVC_H_ + +#include +#include + +class InstallerContext; + +namespace Jobs { +namespace WidgetInstall { +class TaskInstallOspsvc : public DPL::TaskDecl +{ + private: + // Installation context + InstallerContext &m_context; + + void StepInstallOspService(); + + void StepAbortInstall(); + + void StartStep(); + void EndStep(); + + // return callback + static int StatusCallback( + int req_id, const char *pkg_type, const char *pkg_name, + const char *key, const char *val, const void *pmsg, + void *priv_data); + + public: + explicit TaskInstallOspsvc(InstallerContext &installerContext); +}; +} // namespace WidgetInstall +} // namespace Jobs +#endif /* SRC_JOBS_WIDGET_INSTALL_TASK_INSTALL_OSPSVC_H_ */ diff --git a/src_mobile/jobs/widget_install/task_manifest_file.cpp b/src_mobile/jobs/widget_install/task_manifest_file.cpp new file mode 100755 index 0000000..12f19bf --- /dev/null +++ b/src_mobile/jobs/widget_install/task_manifest_file.cpp @@ -0,0 +1,1315 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file task_manifest_file.cpp + * @author Pawel Sikorski (p.sikorski@samgsung.com) + * @version + * @brief + */ + +//SYSTEM INCLUDES +#include +#include +#include +#include +#include +#include + +//WRT INCLUDES +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define DEFAULT_ICON_NAME "icon.png" +#define DEFAULT_PREVIEW_NAME "preview.png" + +using namespace WrtDB; + +namespace { +typedef std::map LanguageTagMap; + +const char* const STR_TRUE = "true"; +const char* const STR_FALSE = "false"; +const char* const STR_NODISPLAY = "nodisplay"; + +LanguageTagMap getLanguageTagMap() +{ + LanguageTagMap map; + +#define ADD(tag, l_tag) map.insert(std::make_pair(L###tag, L###l_tag)); +#include "languages.def" +#undef ADD + + return map; +} + +DPL::OptionalString getLangTag(const DPL::String& tag) +{ + static LanguageTagMap TagsMap = + getLanguageTagMap(); + + DPL::String langTag = tag; + + _D("Trying to map language tag: %ls", langTag.c_str()); + size_t pos = langTag.find_first_of(L'_'); + if (pos != DPL::String::npos) { + langTag.erase(pos); + } + DPL::OptionalString ret; + + LanguageTagMap::iterator it = TagsMap.find(langTag); + if (it != TagsMap.end()) { + ret = it->second; + _D("Mapping IANA Language tag to language tag: %ls -> %ls", langTag.c_str(), (*ret).c_str()); + } + + return ret; +} +} + +namespace Jobs { +namespace WidgetInstall { +const char * TaskManifestFile::encoding = "UTF-8"; + +TaskManifestFile::TaskManifestFile(InstallerContext &inCont) : + DPL::TaskDecl(this), + m_context(inCont), + writer(NULL) +{ + if (m_context.isUpdateMode) { + // for widget update. + AddStep(&TaskManifestFile::stepBackupIconFiles); + AddStep(&TaskManifestFile::stepCopyIconFiles); + AddStep(&TaskManifestFile::stepCopyLiveboxFiles); + AddStep(&TaskManifestFile::stepCopyAccountIconFiles); + AddStep(&TaskManifestFile::stepCreateExecFile); + AddStep(&TaskManifestFile::stepCreateLinkNPPluginsFile); + AddStep(&TaskManifestFile::stepGenerateManifest); + AddAbortStep(&TaskManifestFile::stepAbortIconFiles); + } else { + AddStep(&TaskManifestFile::stepCopyIconFiles); + AddStep(&TaskManifestFile::stepCopyLiveboxFiles); + AddStep(&TaskManifestFile::stepCopyAccountIconFiles); + AddStep(&TaskManifestFile::stepCreateExecFile); + AddStep(&TaskManifestFile::stepCreateLinkNPPluginsFile); + AddStep(&TaskManifestFile::stepGenerateManifest); + } +} + +TaskManifestFile::~TaskManifestFile() +{} + +void TaskManifestFile::stepCreateExecFile() +{ + std::string exec = m_context.locations->getExecFile(); + std::string clientExeStr = GlobalConfig::GetWrtClientExec(); + +#ifdef MULTIPROCESS_SERVICE_SUPPORT + //default widget + std::stringstream postfix; + postfix << AppControlPrefix::PROCESS_PREFIX << 0; + std::string controlExec = exec; + controlExec.append(postfix.str()); + + errno = 0; + if (symlink(clientExeStr.c_str(), controlExec.c_str()) != 0) + { + int error = errno; + if (error) + _E("Failed to make a symbolic name for a file [%s]", DPL::GetErrnoString(error).c_str()); + } + + // app-control widgets + unsigned int indexMax = 0; + FOREACH(it, m_context.widgetConfig.configInfo.appControlList) { + if (it->m_index > indexMax) { + indexMax = it->m_index; + } + } + + for (std::size_t i = 1; i <= indexMax; ++i) { + std::stringstream postfix; + postfix << AppControlPrefix::PROCESS_PREFIX << i; + std::string controlExec = exec; + controlExec.append(postfix.str()); + errno = 0; + if (symlink(clientExeStr.c_str(), controlExec.c_str()) != 0) { + int error = errno; + if (error) { + _E("Failed to make a symbolic name for a file [%s]", DPL::GetErrnoString(error).c_str()); + } + } + } +#else + //default widget + _D("link -s %s %s", clientExeStr.c_str(), exec.c_str()); + errno = 0; + if (symlink(clientExeStr.c_str(), exec.c_str()) != 0) + { + int error = errno; + if (error) + _E("Failed to make a symbolic name for a file [%s]", DPL::GetErrnoString(error).c_str()); + } +#endif + // creation of box symlink + ConfigParserData::LiveboxList& liveboxList = + m_context.widgetConfig.configInfo.m_livebox; + if (!liveboxList.empty()) { + std::string boxExec = "/usr/bin/WebProcess"; + std::string boxSymlink = m_context.locations->getExecFile(); + boxSymlink += ".d-box"; + + errno = 0; + if (symlink(boxExec.c_str(), boxSymlink.c_str()) != 0) { + int error = errno; + if (error) { + _E("Failed to make a symbolic name for a file [%s]", DPL::GetErrnoString(error).c_str()); + } + } + } + + m_context.job->UpdateProgress( + InstallerContext::INSTALL_CREATE_EXECFILE, + "Widget execfile creation Finished"); +} + +void TaskManifestFile::stepCreateLinkNPPluginsFile() +{ + _D("stepCreateLinkNPPluginsFile"); + if (0 == access(m_context.locations->getNPPluginsDir().c_str(), F_OK)) { + _D("This webapp has NPPlugins"); + std::string pluginsExec = "/usr/bin/PluginProcess"; + errno = 0; + if (symlink(pluginsExec.c_str(), + m_context.locations->getNPPluginsExecFile().c_str()) != 0) { + int error = errno; + if (error) { + _E("Failed to create symbolic link for npplugins : %ls", + DPL::GetErrnoString(error).c_str()); + } + } + } +} + +void TaskManifestFile::stepCopyIconFiles() +{ + _D("CopyIconFiles"); + + //This function copies icon to desktop icon path. For each locale avaliable + //which there is at least one icon in widget for, icon file is copied. + //Coping prioritize last positions when coping. If there is several icons + //with given locale, the one, that will be copied, will be icon + //which is declared by tag later than the others in config.xml of + // widget + + std::vector generatedLocales; + + WrtDB::WidgetRegisterInfo::LocalizedIconList & icons = + m_context.widgetConfig.localizationData.icons; + + for (WrtDB::WidgetRegisterInfo::LocalizedIconList::const_iterator + icon = icons.begin(); + icon != icons.end(); + ++icon) + { + DPL::String src = icon->src; + FOREACH(locale, icon->availableLocales) + { + _D("Icon for locale: %ls is: %ls", (*locale).c_str(), src.c_str()); + + if (std::find(generatedLocales.begin(), generatedLocales.end(), + *locale) != generatedLocales.end()) + { + _D("Skipping - has that locale"); + continue; + } else { + generatedLocales.push_back(*locale); + } + + DPL::Utils::Path sourceFile(m_context.locations->getSourceDir()); + if (!locale->empty()) { + sourceFile /= "locales"; + sourceFile /= *locale; + } + sourceFile /= src; + + DPL::Utils::Path targetFile(GlobalConfig::GetUserWidgetDesktopIconPath()); + targetFile /= getIconTargetFilename(*locale, sourceFile.Extension()); + + if (m_context.widgetConfig.packagingType == + WrtDB::PKG_TYPE_HOSTED_WEB_APP) + { + m_context.locations->setIconTargetFilenameForLocale( + targetFile.Fullpath()); + } + + _D("Copying icon: %s -> %s", sourceFile.Filename().c_str(), targetFile.Filename().c_str()); + + icon_list.push_back(targetFile.Fullpath()); + + Try + { + DPL::FileInput input(sourceFile.Fullpath()); + DPL::FileOutput output(targetFile.Fullpath()); + DPL::Copy(&input, &output); + } + + Catch(DPL::FileInput::Exception::Base) + { + // Error while opening or closing source file + //ReThrowMsg(InstallerException::CopyIconFailed, + // sourceFile.str()); + _E("Copying widget's icon failed. Widget's icon will not be" \ + "available from Main Screen"); + } + + Catch(DPL::FileOutput::Exception::Base) + { + // Error while opening or closing target file + //ReThrowMsg(InstallerException::CopyIconFailed, + // targetFile.str()); + _E("Copying widget's icon failed. Widget's icon will not be" \ + "available from Main Screen"); + } + + Catch(DPL::CopyFailed) + { + // Error while copying + //ReThrowMsg(InstallerException::CopyIconFailed, + // targetFile.str()); + _E("Copying widget's icon failed. Widget's icon will not be" \ + "available from Main Screen"); + } + } + } + + m_context.job->UpdateProgress( + InstallerContext::INSTALL_COPY_ICONFILE, + "Widget iconfile copy Finished"); +} + +void TaskManifestFile::stepCopyLiveboxFiles() +{ + _D("Copy Livebox Files"); + + using namespace WrtDB; + ConfigParserData &data = m_context.widgetConfig.configInfo; + ConfigParserData::LiveboxList liveBoxList = data.m_livebox; + + if (liveBoxList.size() <= 0) { + return; + } + + std::ostringstream sourceFile; + std::ostringstream targetFile; + + FOREACH (boxIt, liveBoxList) { + ConfigParserData::LiveboxInfo::BoxSizeList boxSizeList = + (**boxIt).m_boxInfo.m_boxSize; + FOREACH (sizeIt, boxSizeList) { + std::string preview = DPL::ToUTF8String((*sizeIt).m_preview); + if (preview.empty()) { + continue; + } + sourceFile << m_context.locations->getSourceDir() << "/"; + sourceFile << preview; + targetFile << m_context.locations->getSharedDataDir() << "/"; + targetFile << (**boxIt).m_liveboxId << "."; + targetFile << DPL::ToUTF8String((*sizeIt).m_size) << "." << DEFAULT_PREVIEW_NAME; + + copyFile(sourceFile.str(), targetFile.str()); + + // clear stream objects + sourceFile.str(""); + targetFile.str(""); + } + // check this livebox has icon element + std::string icon = DPL::ToUTF8String((**boxIt).m_icon); + if (icon.empty()) { + continue; + } + sourceFile << m_context.locations->getSourceDir() << "/"; + sourceFile << icon; + targetFile << m_context.locations->getSharedDataDir() << "/"; + targetFile << (**boxIt).m_liveboxId << "." << DEFAULT_ICON_NAME; + + copyFile(sourceFile.str(), targetFile.str()); + + // clear stream objects + sourceFile.str(""); + targetFile.str(""); + } + m_context.job->UpdateProgress( + InstallerContext::INSTALL_COPY_LIVEBOX_FILES, + "Livebox files copy Finished"); +} + +void TaskManifestFile::stepCopyAccountIconFiles() +{ + _D("Copy Account icon files"); + WrtDB::ConfigParserData::AccountProvider account = + m_context.widgetConfig.configInfo.accountProvider; + + if (account.m_iconSet.empty()) { + _D("Widget doesn't contain Account"); + return; + } + + FOREACH(it, account.m_iconSet) { + std::string sourceFile = m_context.locations->getSourceDir() + + '/' + + DPL::ToUTF8String(it->second); + std::string targetFile = m_context.locations->getSharedResourceDir() + + '/' + + DPL::ToUTF8String(it->second); + copyFile(sourceFile, targetFile); + } +} + +void TaskManifestFile::copyFile(const std::string& sourceFile, + const std::string& targetFile) +{ + Try + { + DPL::FileInput input(sourceFile); + DPL::FileOutput output(targetFile); + DPL::Copy(&input, &output); + } + Catch(DPL::Exception) + { + _E("Failed to file copy. %s to %s", sourceFile.c_str(), targetFile.c_str()); + ReThrowMsg(Exceptions::CopyIconFailed, "Error during file copy."); + } +} + +bool TaskManifestFile::addBoxUiApplication(Manifest& manifest) +{ + UiApplication uiApp; + std::string postfix = ".d-box"; + static bool isAdded = false; + + Try + { + if (isAdded) { + _D("UiApplication for d-box is already added"); + return false; + } + uiApp.setNodisplay(true); + uiApp.setTaskmanage(false); + uiApp.setMultiple(false); + setWidgetName(manifest, uiApp); + setWidgetIcons(uiApp); + + // appid for box is like [webapp id].d-box + setWidgetIds(manifest, uiApp, postfix); + // executable path for box is like [app path]/bin/[webapp id].d-box + setWidgetExecPath(uiApp, postfix); + manifest.addUiApplication(uiApp); + isAdded = true; + + return true; + } + Catch(DPL::Exception) + { + _E("Adding UiApplication on xml is failed."); + isAdded = false; + return false; + } +} + +void TaskManifestFile::stepBackupIconFiles() +{ + _D("Backup Icon Files"); + + backup_dir << m_context.locations->getBackupDir() << "/"; + + backupIconFiles(); + + m_context.job->UpdateProgress( + InstallerContext::INSTALL_BACKUP_ICONFILE, + "New Widget icon file backup Finished"); +} + +void TaskManifestFile::stepAbortIconFiles() +{ + _D("Abrot Icon Files"); + FOREACH(it, icon_list) + { + _D("Remove Update Icon : %s", (*it).c_str()); + unlink((*it).c_str()); + } + + std::ostringstream b_icon_dir; + b_icon_dir << backup_dir.str() << "icons"; + + std::list fileList; + getFileList(b_icon_dir.str().c_str(), fileList); + + FOREACH(back_icon, fileList) + { + std::ostringstream res_file; + res_file << GlobalConfig::GetUserWidgetDesktopIconPath(); + res_file << "/" << (*back_icon); + + std::ostringstream backup_file; + backup_file << b_icon_dir.str() << "/" << (*back_icon); + + Try + { + DPL::FileInput input(backup_file.str()); + DPL::FileOutput output(res_file.str()); + DPL::Copy(&input, &output); + } + Catch(DPL::FileInput::Exception::Base) + { + _E("Restoration icon File Failed. %s to %s", backup_file.str().c_str(), res_file.str().c_str()); + } + + Catch(DPL::FileOutput::Exception::Base) + { + _E("Restoration icon File Failed. %s to %s", backup_file.str().c_str(), res_file.str().c_str()); + } + Catch(DPL::CopyFailed) + { + _E("Restoration icon File Failed. %s to %s", backup_file.str().c_str(), res_file.str().c_str()); + } + } +} + +DPL::String TaskManifestFile::getIconTargetFilename( + const DPL::String& languageTag, const std::string & ext) const +{ + DPL::OStringStream filename; + TizenAppId appid = m_context.widgetConfig.tzAppid; + + filename << DPL::ToUTF8String(appid).c_str(); + + if (!languageTag.empty()) { + DPL::OptionalString tag = getLangTag(languageTag); // translate en -> + // en_US etc + if (tag.IsNull()) { + tag = languageTag; + } + DPL::String locale = + LanguageTagsProvider::BCP47LanguageTagToLocale(*tag); + + if (locale.empty()) { + filename << L"." << languageTag; + } else { + filename << L"." << locale; + } + } + + if(!ext.empty()) + { + filename << L"." + DPL::FromUTF8String(ext); + } + return filename.str(); +} + +void TaskManifestFile::saveLocalizedKey(std::ofstream &file, + const DPL::String& key, + const DPL::String& languageTag) +{ + DPL::String locale = + LanguageTagsProvider::BCP47LanguageTagToLocale(languageTag); + + file << key; + if (!locale.empty()) { + file << "[" << locale << "]"; + } + file << "="; +} + +void TaskManifestFile::backupIconFiles() +{ + _D("Backup Icon Files"); + + std::ostringstream b_icon_dir; + b_icon_dir << backup_dir.str() << "icons"; + + _D("Create icon backup folder : %s", b_icon_dir.str().c_str()); + WrtUtilMakeDir(b_icon_dir.str()); + + std::list fileList; + getFileList(GlobalConfig::GetUserWidgetDesktopIconPath(), fileList); + std::string appid = DPL::ToUTF8String(m_context.widgetConfig.tzAppid); + + FOREACH(it, fileList) + { + if (0 == (strncmp((*it).c_str(), appid.c_str(), + strlen(appid.c_str())))) + { + std::ostringstream icon_file, backup_icon; + icon_file << GlobalConfig::GetUserWidgetDesktopIconPath(); + icon_file << "/" << (*it); + + backup_icon << b_icon_dir.str() << "/" << (*it); + + _D("Backup icon file %s to %s", icon_file.str().c_str(), backup_icon.str().c_str()); + Try + { + DPL::FileInput input(icon_file.str()); + DPL::FileOutput output(backup_icon.str()); + DPL::Copy(&input, &output); + } + Catch(DPL::FileInput::Exception::Base) + { + _E("Backup Desktop File Failed."); + ReThrowMsg(Exceptions::BackupFailed, icon_file.str()); + } + + Catch(DPL::FileOutput::Exception::Base) + { + _E("Backup Desktop File Failed."); + ReThrowMsg(Exceptions::BackupFailed, backup_icon.str()); + } + Catch(DPL::CopyFailed) + { + _E("Backup Desktop File Failed."); + ReThrowMsg(Exceptions::BackupFailed, backup_icon.str()); + } + unlink((*it).c_str()); + } + } +} + +void TaskManifestFile::getFileList(const char* path, + std::list &list) +{ + DIR* dir = opendir(path); + if (!dir) { + _E("icon directory doesn't exist"); + ThrowMsg(Exceptions::FileOperationFailed, path); + } + + struct dirent entry; + struct dirent *result; + int return_code; + errno = 0; + for (return_code = readdir_r(dir, &entry, &result); + result != NULL && return_code == 0; + return_code = readdir_r(dir, &entry, &result)) + { + if (strcmp(entry.d_name, ".") == 0 || + strcmp(entry.d_name, "..") == 0) + { + continue; + } + std::string file_name = entry.d_name; + list.push_back(file_name); + } + + if (return_code != 0 || errno != 0) { + _E("readdir_r() failed with %s", DPL::GetErrnoString().c_str()); + } + + if (-1 == closedir(dir)) { + _E("Failed to close dir: %s with error: %s", path, DPL::GetErrnoString().c_str()); + } +} + +void TaskManifestFile::stepGenerateManifest() +{ + TizenPkgId pkgid = m_context.widgetConfig.tzPkgid; + manifest_name = pkgid + L".xml"; + manifest_file += L"/tmp/" + manifest_name; + + //libxml - init and check + LibxmlSingleton::Instance().init(); + + writeManifest(manifest_file); + + std::ostringstream destFile; + if (m_context.mode.rootPath == InstallMode::RootPath::RO) { + destFile << WrtDB::GlobalConfig::GetPreloadManifestPath() << "/"; + } else { + destFile << WrtDB::GlobalConfig::GetManifestPath() << "/"; + } + + destFile << DPL::ToUTF8String(manifest_name); + commit_manifest = destFile.str(); + _D("Commiting manifest file : %s", commit_manifest.c_str()); + + commitManifest(); + + m_context.job->UpdateProgress( + InstallerContext::INSTALL_CREATE_MANIFEST, + "Widget Manifest Creation Finished"); +} + +void TaskManifestFile::commitManifest() +{ + + if (!(m_context.mode.rootPath == InstallMode::RootPath::RO && + m_context.mode.installTime == InstallMode::InstallTime::PRELOAD + && m_context.mode.extension == InstallMode::ExtensionType::DIR)) { + _D("cp %ls %s", manifest_file.c_str(), commit_manifest.c_str()); + + DPL::FileInput input(DPL::ToUTF8String(manifest_file)); + DPL::FileOutput output(commit_manifest); + DPL::Copy(&input, &output); + _D("Manifest writen to: %s", commit_manifest.c_str()); + + //removing temp file + unlink((DPL::ToUTF8String(manifest_file)).c_str()); + manifest_file = DPL::FromUTF8String(commit_manifest); + } +} + +void TaskManifestFile::writeManifest(const DPL::String & path) +{ + _D("Generating manifest file : %ls", path.c_str()); + Manifest manifest; + UiApplication uiApp; + +#ifdef MULTIPROCESS_SERVICE_SUPPORT + //default widget content + std::stringstream postfix; + // index 0 is reserved + postfix << AppControlPrefix::PROCESS_PREFIX << 0; + setWidgetExecPath(uiApp, postfix.str()); + setWidgetName(manifest, uiApp); + setWidgetIds(manifest, uiApp); + setWidgetIcons(uiApp); + setWidgetDescription(manifest); + setWidgetManifest(manifest); + setWidgetOtherInfo(uiApp); + setAppCategory(uiApp); + setMetadata(uiApp); + // move to the last of this procedure + //setLiveBoxInfo(manifest); + setAccount(manifest); + setPrivilege(manifest); + manifest.addUiApplication(uiApp); + + //app-control content + ConfigParserData::AppControlInfoList appControlList = + m_context.widgetConfig.configInfo.appControlList; + FOREACH(it, appControlList) { + UiApplication uiApp; + + uiApp.setTaskmanage(true); + uiApp.setNodisplay(true); +#ifdef MULTIPROCESS_SERVICE_SUPPORT_INLINE + uiApp.setTaskmanage(ConfigParserData::AppControlInfo::Disposition::INLINE != it->m_disposition); + uiApp.setMultiple(ConfigParserData::AppControlInfo::Disposition::INLINE == it->m_disposition); +#endif + std::stringstream postfix; + postfix << AppControlPrefix::PROCESS_PREFIX << it->m_index; + setWidgetExecPath(uiApp, postfix.str()); + setWidgetName(manifest, uiApp); + setWidgetIds(manifest, uiApp); + setWidgetIcons(uiApp); + setAppControlInfo(uiApp, *it); + setAppCategory(uiApp); + setMetadata(uiApp); + manifest.addUiApplication(uiApp); + } + // TODO: Must fix again with right method + // The mainapp attiribute must be set + // when there are multiple uiapps in mainfest + setLiveBoxInfo(manifest); +#else + //default widget content + setWidgetExecPath(uiApp); + setWidgetName(manifest, uiApp); + setWidgetIds(manifest, uiApp); + setWidgetIcons(uiApp); + setWidgetDescription(manifest); + setWidgetManifest(manifest); + setWidgetOtherInfo(uiApp); + setAppControlsInfo(uiApp); + setAppCategory(uiApp); + setMetadata(uiApp); + // move to the last of this procedure + //setLiveBoxInfo(manifest); + setAccount(manifest); + setPrivilege(manifest); + + manifest.addUiApplication(uiApp); + // TODO: Must fix again with right method + // The mainapp attiribute must be set + // when there are multiple uiapps in mainfest + setLiveBoxInfo(manifest); +#endif + + manifest.generate(path); + _D("Manifest file serialized"); +} + +void TaskManifestFile::setWidgetExecPath(UiApplication & uiApp, + const std::string &postfix) +{ + std::string exec = m_context.locations->getExecFile(); + if (!postfix.empty()) { + exec.append(postfix); + } + _D("exec = %s", exec.c_str()); + uiApp.setExec(DPL::FromASCIIString(exec)); +} + +void TaskManifestFile::setWidgetName(Manifest & manifest, + UiApplication & uiApp) +{ + bool defaultNameSaved = false; + + DPL::OptionalString defaultLocale = + m_context.widgetConfig.configInfo.defaultlocale; + std::pair defaultLocalizedData; + //labels + FOREACH(localizedData, m_context.widgetConfig.configInfo.localizedDataSet) + { + Locale i = localizedData->first; + DPL::OptionalString tag = getLangTag(i); // translate en -> en_US etc + if (tag.IsNull()) { + tag = i; + } + DPL::OptionalString name = localizedData->second.name; + generateWidgetName(manifest, uiApp, tag, name, defaultNameSaved); + + //store default locale localized data + if (!!defaultLocale && defaultLocale == i) { + defaultLocalizedData = *localizedData; + } + } + + if (!!defaultLocale && !defaultNameSaved) { + DPL::OptionalString name = defaultLocalizedData.second.name; + generateWidgetName(manifest, + uiApp, + DPL::OptionalString::Null, + name, + defaultNameSaved); + } +} + +void TaskManifestFile::setWidgetIds(Manifest & manifest, + UiApplication & uiApp, + const std::string &postfix) +{ + //appid + TizenAppId appid = m_context.widgetConfig.tzAppid; + if (!postfix.empty()) { + appid = DPL::FromUTF8String(DPL::ToUTF8String(appid).append(postfix)); + } + uiApp.setAppid(appid); + + //extraid + if (!!m_context.widgetConfig.guid) { + uiApp.setExtraid(*m_context.widgetConfig.guid); + } else { + if (!appid.empty()) { + uiApp.setExtraid(DPL::String(L"http://") + appid); + } + } + + //type + uiApp.setType(DPL::FromASCIIString("webapp")); + manifest.setType(L"wgt"); +} + +void TaskManifestFile::generateWidgetName(Manifest & manifest, + UiApplication &uiApp, + const DPL::OptionalString& tag, + DPL::OptionalString name, + bool & defaultNameSaved) +{ + if (!!name) { + if (!!tag) { + DPL::String locale = + LanguageTagsProvider::BCP47LanguageTagToLocale(*tag); + + if (!locale.empty()) { + uiApp.addLabel(LabelType(*name, *tag)); + } else { + uiApp.addLabel(LabelType(*name)); + manifest.addLabel(LabelType(*name)); + } + } else { + defaultNameSaved = true; + uiApp.addLabel(LabelType(*name)); + manifest.addLabel(LabelType(*name)); + } + } +} + +void TaskManifestFile::setWidgetIcons(UiApplication & uiApp) +{ + //TODO this file will need to be updated when user locale preferences + //changes. + bool defaultIconSaved = false; + + DPL::OptionalString defaultLocale = + m_context.widgetConfig.configInfo.defaultlocale; + + std::vector generatedLocales; + WrtDB::WidgetRegisterInfo::LocalizedIconList & icons = + m_context.widgetConfig.localizationData.icons; + + for (WrtDB::WidgetRegisterInfo::LocalizedIconList::const_iterator + icon = icons.begin(); + icon != icons.end(); + ++icon) + { + FOREACH(locale, icon->availableLocales) + { + if (std::find(generatedLocales.begin(), generatedLocales.end(), + *locale) != generatedLocales.end()) + { + _D("Skipping - has that locale - already in manifest"); + continue; + } else { + generatedLocales.push_back(*locale); + } + + DPL::OptionalString tag = getLangTag(*locale); // translate en -> + // en_US etc + if (tag.IsNull()) { + tag = *locale; + } + + generateWidgetIcon(uiApp, tag, *locale, DPL::Utils::Path(icon->src).Extension(), defaultIconSaved); + } + } + if (!!defaultLocale && !defaultIconSaved) { + generateWidgetIcon(uiApp, DPL::OptionalString::Null, + DPL::String(), + std::string(), + defaultIconSaved); + } +} + +void TaskManifestFile::generateWidgetIcon(UiApplication & uiApp, + const DPL::OptionalString& tag, + const DPL::String& language, + const std::string & extension, + bool & defaultIconSaved) +{ + DPL::String locale; + if (!!tag) { + locale = LanguageTagsProvider::BCP47LanguageTagToLocale(*tag); + } else { + defaultIconSaved = true; + } + + DPL::String iconText; + iconText += getIconTargetFilename(language, extension); + + if (!locale.empty()) { + uiApp.addIcon(IconType(iconText, locale)); + } else { + uiApp.addIcon(IconType(iconText)); + } + std::ostringstream iconPath; + iconPath << GlobalConfig::GetUserWidgetDesktopIconPath() << "/"; + iconPath << getIconTargetFilename(locale, extension); + m_context.job->SendProgressIconPath(iconPath.str()); +} + +void TaskManifestFile::setWidgetDescription(Manifest & manifest) +{ + FOREACH(localizedData, m_context.widgetConfig.configInfo.localizedDataSet) + { + Locale i = localizedData->first; + DPL::OptionalString tag = getLangTag(i); // translate en -> en_US etc + if (tag.IsNull()) { + tag = i; + } + DPL::OptionalString description = localizedData->second.description; + generateWidgetDescription(manifest, tag, description); + } +} + +void TaskManifestFile::generateWidgetDescription(Manifest & manifest, + const DPL::OptionalString& tag, + DPL::OptionalString description) +{ + if (!!description) { + if (!!tag) { + DPL::String locale = + LanguageTagsProvider::BCP47LanguageTagToLocale(*tag); + if (!locale.empty()) { + manifest.addDescription(DescriptionType(*description, locale)); + } else { + manifest.addDescription(DescriptionType(*description)); + } + } else { + manifest.addDescription(DescriptionType(*description)); + } + } +} + +void TaskManifestFile::setWidgetManifest(Manifest & manifest) +{ + manifest.setPackage(m_context.widgetConfig.tzPkgid); + + if (!!m_context.widgetConfig.version) { + manifest.setVersion(*m_context.widgetConfig.version); + } + DPL::String email = (!!m_context.widgetConfig.configInfo.authorEmail ? + *m_context.widgetConfig.configInfo.authorEmail : L""); + DPL::String href = (!!m_context.widgetConfig.configInfo.authorHref ? + *m_context.widgetConfig.configInfo.authorHref : L""); + DPL::String name = (!!m_context.widgetConfig.configInfo.authorName ? + *m_context.widgetConfig.configInfo.authorName : L""); + manifest.addAuthor(Author(email, href, L"", name)); + + if (!m_context.callerPkgId.empty()) { + manifest.setStoreClientId(m_context.callerPkgId); + } +} + +void TaskManifestFile::setWidgetOtherInfo(UiApplication & uiApp) +{ + FOREACH(it, m_context.widgetConfig.configInfo.settingsList) + { + if (!strcmp(DPL::ToUTF8String(it->m_name).c_str(), STR_NODISPLAY)) { + if (!strcmp(DPL::ToUTF8String(it->m_value).c_str(), STR_TRUE)) { + uiApp.setNodisplay(true); + uiApp.setTaskmanage(false); + } else { + uiApp.setNodisplay(false); + uiApp.setTaskmanage(true); + } + } + } + //TODO + //There is no "X-TIZEN-PackageType=wgt" + //There is no X-TIZEN-PackageID in manifest "X-TIZEN-PackageID=" << + // DPL::ToUTF8String(*widgetID).c_str() + //There is no Comment in pkgmgr "Comment=Widget application" + //that were in desktop file +} + +void TaskManifestFile::setAppControlsInfo(UiApplication & uiApp) +{ + WrtDB::ConfigParserData::AppControlInfoList appControlList = + m_context.widgetConfig.configInfo.appControlList; + + if (appControlList.empty()) { + _D("Widget doesn't contain app control"); + return; + } + + // x-tizen-svc=http://tizen.org/appcontrol/operation/pick|NULL|image; + FOREACH(it, appControlList) { + setAppControlInfo(uiApp, *it); + } +} + +void TaskManifestFile::setAppControlInfo(UiApplication & uiApp, + const WrtDB::ConfigParserData::AppControlInfo & service) +{ + // x-tizen-svc=http://tizen.org/appcontrol/operation/pick|NULL|image; + AppControl appControl; + if (!service.m_operation.empty()) { + appControl.addOperation(service.m_operation); //TODO: encapsulation? + } + if (!service.m_uriList.empty()) { + FOREACH(uri, service.m_uriList) { + appControl.addUri(*uri); + } + } + if (!service.m_mimeList.empty()) { + FOREACH(mime, service.m_mimeList) { + appControl.addMime(*mime); + } + } + uiApp.addAppControl(appControl); +} + +void TaskManifestFile::setAppCategory(UiApplication &uiApp) +{ + WrtDB::ConfigParserData::CategoryList categoryList = + m_context.widgetConfig.configInfo.categoryList; + + if (categoryList.empty()) { + _D("Widget doesn't contain application category"); + return; + } + FOREACH(it, categoryList) { + if (!(*it).empty()) { + uiApp.addAppCategory(*it); + } + } +} + +void TaskManifestFile::setMetadata(UiApplication &uiApp) +{ + WrtDB::ConfigParserData::MetadataList metadataList = + m_context.widgetConfig.configInfo.metadataList; + + if (metadataList.empty()) { + _D("Web application doesn't contain metadata"); + return; + } + FOREACH(it, metadataList) { + MetadataType metadataType(it->key, it->value); + uiApp.addMetadata(metadataType); + } +} + +void TaskManifestFile::setLiveBoxInfo(Manifest& manifest) +{ + ConfigParserData::LiveboxList& liveboxList = + m_context.widgetConfig.configInfo.m_livebox; + + if (liveboxList.empty()) { + _D("no livebox"); + return; + } + + if (!addBoxUiApplication(manifest)) { + _D("error during adding UiApplication for d-box"); + return; + } + + FOREACH(it, liveboxList) { + _D("setLiveBoxInfo"); + LiveBoxInfo liveBox; + DPL::Optional ConfigInfo = *it; + DPL::String appid = m_context.widgetConfig.tzAppid; + + if (ConfigInfo->m_liveboxId != L"") { + size_t found = ConfigInfo->m_liveboxId.find_last_of(L"."); + if (found != std::string::npos) { + if (0 == ConfigInfo->m_liveboxId.compare(0, found, appid)) { + liveBox.setLiveboxId(ConfigInfo->m_liveboxId); + } else { + DPL::String liveboxId = + appid + DPL::String(L".") + ConfigInfo->m_liveboxId; + liveBox.setLiveboxId(liveboxId); + } + } else { + DPL::String liveboxId = + appid + DPL::String(L".") + ConfigInfo->m_liveboxId; + liveBox.setLiveboxId(liveboxId); + } + } + + if (ConfigInfo->m_primary != L"") { + liveBox.setPrimary(ConfigInfo->m_primary); + } + + if (ConfigInfo->m_updatePeriod != L"") { + liveBox.setUpdatePeriod(ConfigInfo->m_updatePeriod); + } + + std::list > boxLabelList; + if (!ConfigInfo->m_label.empty()) { + FOREACH(im, ConfigInfo->m_label) { + std::pair boxSize; + Locale i = (*im).first; + // translate en -> en_US etc + DPL::OptionalString tag = getLangTag(i); + if (tag.IsNull()) { + tag = i; + } + boxSize.first = (*tag); + boxSize.second = (*im).second; + boxLabelList.push_back(boxSize); + } + liveBox.setLabel(boxLabelList); + } + + DPL::String defaultLocale = + DPL::FromUTF8String(m_context.locations->getPackageInstallationDir()) + + DPL::String(L"/res/wgt/"); + + if (ConfigInfo->m_icon != L"") { + DPL::String icon = + DPL::FromUTF8String(m_context.locations->getSharedDataDir()) + + DPL::String(L"/") + + ConfigInfo->m_liveboxId + DPL::String(L".icon.png"); + liveBox.setIcon(icon); + } + + if (ConfigInfo->m_boxInfo.m_boxSrc.empty() || + ConfigInfo->m_boxInfo.m_boxSize.empty()) + { + _D("Widget doesn't contain box"); + return; + } else { + BoxInfoType box; + if (!ConfigInfo->m_boxInfo.m_boxSrc.empty()) { + if ((0 == ConfigInfo->m_boxInfo.m_boxSrc.compare(0, 4, L"http")) + || (0 == + ConfigInfo->m_boxInfo.m_boxSrc.compare(0, 5, L"https"))) + { + box.boxSrc = ConfigInfo->m_boxInfo.m_boxSrc; + } else { + box.boxSrc = defaultLocale + ConfigInfo->m_boxInfo.m_boxSrc; + } + } + + if (ConfigInfo->m_boxInfo.m_boxMouseEvent == L"true") { + std::string boxType; + if (ConfigInfo->m_type == L"") { + // in case of default livebox + boxType = web_provider_livebox_get_default_type(); + } else { + boxType = DPL::ToUTF8String(ConfigInfo->m_type); + } + + int box_scrollable = + web_provider_plugin_get_box_scrollable(boxType.c_str()); + + if (box_scrollable) { + box.boxMouseEvent = L"true"; + } else { + box.boxMouseEvent = L"false"; + } + } else { + box.boxMouseEvent = L"false"; + } + + if (ConfigInfo->m_boxInfo.m_boxTouchEffect == L"true") { + box.boxTouchEffect = L"true"; + } else { + box.boxTouchEffect= L"false"; + } + + ConfigParserData::LiveboxInfo::BoxSizeList boxSizeList = + ConfigInfo->m_boxInfo.m_boxSize; + FOREACH(it, boxSizeList) { + if (!(*it).m_preview.empty()) { + (*it).m_preview = + DPL::FromUTF8String(m_context.locations->getSharedDataDir()) + + DPL::String(L"/") + + ConfigInfo->m_liveboxId + DPL::String(L".") + + (*it).m_size + DPL::String(L".preview.png"); + } + box.boxSize.push_back((*it)); + } + + if (!ConfigInfo->m_boxInfo.m_pdSrc.empty() + && !ConfigInfo->m_boxInfo.m_pdWidth.empty() + && !ConfigInfo->m_boxInfo.m_pdHeight.empty()) + { + if ((0 == ConfigInfo->m_boxInfo.m_pdSrc.compare(0, 4, L"http")) + || (0 == ConfigInfo->m_boxInfo.m_pdSrc.compare(0, 5, L"https"))) + { + box.pdSrc = ConfigInfo->m_boxInfo.m_pdSrc; + } else { + box.pdSrc = defaultLocale + ConfigInfo->m_boxInfo.m_pdSrc; + } + box.pdWidth = ConfigInfo->m_boxInfo.m_pdWidth; + box.pdHeight = ConfigInfo->m_boxInfo.m_pdHeight; + } + liveBox.setBox(box); + } + manifest.addLivebox(liveBox); + } +} + +void TaskManifestFile::setAccount(Manifest& manifest) +{ + WrtDB::ConfigParserData::AccountProvider account = + m_context.widgetConfig.configInfo.accountProvider; + + AccountProviderType provider; + + if (account.m_iconSet.empty()) { + _D("Widget doesn't contain Account"); + return; + } + if (account.m_multiAccountSupport) { + provider.multiAccount = L"true"; + } else { + provider.multiAccount = L"false"; + } + provider.appid = m_context.widgetConfig.tzAppid; + + FOREACH(it, account.m_iconSet) { + std::pair icon; + + if (it->first == ConfigParserData::IconSectionType::DefaultIcon) { + icon.first = L"account"; + } else if (it->first == ConfigParserData::IconSectionType::SmallIcon) { + icon.first = L"account-small"; + } + + // account manifest requires absolute path for icon + // /opt/apps/[package]/shared/res/[icon_path] + icon.second = DPL::FromUTF8String(m_context.locations->getSharedResourceDir()) + + DPL::String(L"/") + + it->second; + provider.icon.push_back(icon); + } + + FOREACH(it, account.m_displayNameSet) { + provider.name.push_back(LabelType(it->second, it->first)); + } + + FOREACH(it, account.m_capabilityList) { + provider.capability.push_back(*it); + } + + Account accountInfo; + accountInfo.addAccountProvider(provider); + manifest.addAccount(accountInfo); +} + +void TaskManifestFile::setPrivilege(Manifest& manifest) +{ + WrtDB::ConfigParserData::PrivilegeList privileges = + m_context.widgetConfig.configInfo.privilegeList; + + PrivilegeType privilege; + + FOREACH(it, privileges) + { + privilege.addPrivilegeName(it->name); + } + + manifest.addPrivileges(privilege); +} + +void TaskManifestFile::StartStep() +{ + +} + +void TaskManifestFile::EndStep() +{ + +} +} //namespace WidgetInstall +} //namespace Jobs diff --git a/src_mobile/jobs/widget_install/task_manifest_file.h b/src_mobile/jobs/widget_install/task_manifest_file.h new file mode 100644 index 0000000..afcb00d --- /dev/null +++ b/src_mobile/jobs/widget_install/task_manifest_file.h @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file task_manifest_file.h + * @author Pawel Sikorski (p.sikorski@samgsung.com) + * @version + * @brief + */ + +#ifndef INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_DESKTOP_FILE_H +#define INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_DESKTOP_FILE_H + +//SYSTEM INCLUDES +#include + +//WRT INCLUDES +#include +#include + +#include + +#include +#include +#include + +#include + +class InstallerContext; + +namespace Jobs { +namespace WidgetInstall { +class TaskManifestFile : + public DPL::TaskDecl +{ + public: + + DECLARE_EXCEPTION_TYPE(DPL::Exception, Base) + DECLARE_EXCEPTION_TYPE(Base, ManifestValidationError) + DECLARE_EXCEPTION_TYPE(Base, ManifestParsingError) + + TaskManifestFile(InstallerContext &inCont); + virtual ~TaskManifestFile(); + + private: + //context data + InstallerContext &m_context; + + //TODO stepAbort + //steps + void stepCreateExecFile(); + void stepCopyIconFiles(); + void stepCopyLiveboxFiles(); + void stepCopyAccountIconFiles(); + void stepGenerateManifest(); + void stepCreateLinkNPPluginsFile(); + + void stepAbortParseManifest(); + + //For widget update + void stepBackupIconFiles(); + void stepAbortIconFiles(); + + void StartStep(); + void EndStep(); + + //private data + std::list icon_list; //TODO: this should be registered as + // external files + std::ostringstream backup_dir; + xmlTextWriterPtr writer; + DPL::String manifest_name; + DPL::String manifest_file; + std::string commit_manifest; + + //private methods + + void writeManifest(const DPL::String & path); + void commitManifest(); + + void setWidgetExecPath(UiApplication & uiApp, + const std::string &postfix = std::string()); + void setWidgetName(Manifest & manifest, + UiApplication & uiApp); + void setWidgetIds(Manifest & manifest, + UiApplication & uiApp, + const std::string &postfix = std::string()); + void setWidgetIcons(UiApplication & uiApp); + void setWidgetDescription(Manifest & manifest); + void setWidgetManifest(Manifest & manifest); + void setWidgetOtherInfo(UiApplication & uiApp); + void setAppControlsInfo(UiApplication & uiApp); + void setAppControlInfo(UiApplication & uiApp, + const WrtDB::ConfigParserData::AppControlInfo & service); + void setAppCategory(UiApplication & uiApp); + void setMetadata(UiApplication & uiApp); + void setLiveBoxInfo(Manifest& manifest); + void setAccount(Manifest& uiApp); + void setPrivilege(Manifest& manifest); + + void generateWidgetName(Manifest & manifest, + UiApplication &uiApp, + const DPL::OptionalString& tag, + DPL::OptionalString name, + bool & defaultNameSaved); + void generateWidgetDescription(Manifest & manifest, + const DPL::OptionalString& tag, + DPL::OptionalString description); + void generateWidgetIcon(UiApplication & uiApp, + const DPL::OptionalString& tag, + const DPL::String& language, const std::string &extension, + bool & defaultIconSaved); + void copyFile(const std::string& sourceFile, + const std::string& targetFile); + bool addBoxUiApplication(Manifest& manifest); + + //for widget update + void backupIconFiles(); + void getFileList(const char* path, std::list &list); + DPL::String getIconTargetFilename(const DPL::String& languageTag, + const std::string & ext) const; + + static void saveLocalizedKey(std::ofstream &file, + const DPL::String& key, + const DPL::String& languageTag); + + static const char * encoding; +}; +} //namespace WidgetInstall +} //namespace Jobs + +#endif /* INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_DESKTOP_FILE_H */ diff --git a/src_mobile/jobs/widget_install/task_pkg_info_update.cpp b/src_mobile/jobs/widget_install/task_pkg_info_update.cpp new file mode 100644 index 0000000..4bd0898 --- /dev/null +++ b/src_mobile/jobs/widget_install/task_pkg_info_update.cpp @@ -0,0 +1,289 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file task_pkg_info_update.cpp + * @author Soyoung Kim (sy037.kim@samsung.com) + * @version 1.0 + * @brief Implementation file for installer task information about package + * update + */ +#include "task_pkg_info_update.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +using namespace WrtDB; + +namespace { +} + +namespace Jobs { +namespace WidgetInstall { +TaskPkgInfoUpdate::TaskPkgInfoUpdate(InstallerContext& context) : + DPL::TaskDecl(this), + m_context(context) +{ + AddStep(&TaskPkgInfoUpdate::StartStep); + AddStep(&TaskPkgInfoUpdate::StepPkgInfo); + AddStep(&TaskPkgInfoUpdate::StepSetCertiInfo); + AddStep(&TaskPkgInfoUpdate::EndStep); + AddStep(&TaskPkgInfoUpdate::StepSetEndofInstallation); + + AddAbortStep(&TaskPkgInfoUpdate::StepAbortCertiInfo); + AddAbortStep(&TaskPkgInfoUpdate::stepAbortParseManifest); +} + +void TaskPkgInfoUpdate::StepPkgInfo() +{ + int code = 0; + char* updateTags[3] = {NULL, }; + + char preloadTrue[] = "preload=true"; + char removableTrue[] = "removable=true"; + char removableFalse[] = "removable=false"; + + if (InstallMode::InstallTime::CSC == m_context.mode.installTime) { + updateTags[0] = preloadTrue; + if (m_context.mode.removable) { + updateTags[1] = removableTrue; + } else { + updateTags[1] = removableFalse; + } + updateTags[2] = NULL; + } + + if (m_context.mode.rootPath == InstallMode::RootPath::RO) { + m_manifest += "/usr/share/packages/"; + } else { + m_manifest += "/opt/share/packages/"; + } + m_manifest += DPL::ToUTF8String(m_context.widgetConfig.tzPkgid) + ".xml"; + _D("manifest file : %s", m_manifest.c_str()); + + if (m_context.isUpdateMode || ( + m_context.mode.rootPath == InstallMode::RootPath::RO + && m_context.mode.installTime == InstallMode::InstallTime::PRELOAD + && m_context.mode.extension == InstallMode::ExtensionType::DIR)) { + + code = pkgmgr_parser_parse_manifest_for_upgrade( + m_manifest.c_str(), (updateTags[0] == NULL) ? NULL : updateTags); + + if (code != 0) { + _E("Manifest parser error: %d", code); + ThrowMsg(Exceptions::ManifestInvalid, "Parser returncode: " << code); + } + } else { + code = pkgmgr_parser_parse_manifest_for_installation( + m_manifest.c_str(), (updateTags[0] == NULL) ? NULL : updateTags); + + if (code != 0) { + _E("Manifest parser error: %d", code); + ThrowMsg(Exceptions::ManifestInvalid, "Parser returncode: " << code); + } + } + + m_context.job->UpdateProgress( + InstallerContext::INSTALL_PKGINFO_UPDATE, + "Manifest Update Finished"); + _D("Manifest parsed"); +} + +void TaskPkgInfoUpdate::StepSetCertiInfo() +{ + _D("StepSetCertiInfo"); + + if (pkgmgr_installer_create_certinfo_set_handle(&m_pkgHandle) < 0) { + _E("pkgmgrInstallerCreateCertinfoSetHandle fail"); + ThrowMsg(Exceptions::SetCertificateInfoFailed, + "Failed to create certificate handle"); + } + + SetCertiInfo(SIGNATURE_AUTHOR); + SetCertiInfo(SIGNATURE_DISTRIBUTOR); + + if ((pkgmgr_installer_save_certinfo( + const_cast(DPL::ToUTF8String( + m_context.widgetConfig.tzPkgid).c_str()), + m_pkgHandle)) < 0) + { + _E("pkgmgrInstallerSaveCertinfo fail"); + ThrowMsg(Exceptions::SetCertificateInfoFailed, + "Failed to Installer Save Certinfo"); + } else { + _D("Succeed to save Certinfo"); + } + + if (pkgmgr_installer_destroy_certinfo_set_handle(m_pkgHandle) < 0) { + _E("pkgmgrInstallerDestroyCertinfoSetHandle fail"); + } +} + +void TaskPkgInfoUpdate::SetCertiInfo(int source) +{ + _D("Set CertiInfo to pkgmgr : %d", source); + CertificateChainList certificateChainList; + m_context.widgetSecurity.getCertificateChainList(certificateChainList, + (CertificateSource)source); + + FOREACH(it, certificateChainList) + { + _D("Insert certinfo to pkgmgr structure"); + + ValidationCore::CertificateCollection chain; + + if (false == chain.load(*it)) { + _E("Chain is broken"); + ThrowMsg(Exceptions::SetCertificateInfoFailed, + "Failed to Installer Save Certinfo"); + } + + if (!chain.sort()) { + _E("Chain failed at sorting"); + } + + ValidationCore::CertificateList list = chain.getCertificateList(); + + FOREACH(certIt, list) + { + pkgmgr_instcert_type instCertType; + + if (source == SIGNATURE_DISTRIBUTOR) { + bool distributor1 = false; + if (!(*certIt)->getCommonName().IsNull()) { + std::string + Name(DPL::ToUTF8String(*(*certIt)->getCommonName())); + std::string tizenStr("Tizen"); + if (0 == Name.compare(0, tizenStr.length(), tizenStr)) { + distributor1 = true; + } + } + + if (distributor1) { + _D("Set SIGNATURE_DISTRIBUTOR"); + if ((*certIt)->isRootCert()) { + instCertType = PM_SET_DISTRIBUTOR_ROOT_CERT; + } else { + if ((*certIt)->isCA()) { + instCertType = PM_SET_DISTRIBUTOR_INTERMEDIATE_CERT; + } else { + instCertType = PM_SET_DISTRIBUTOR_SIGNER_CERT; + } + } + } else { + _D("Set SIGNATURE_DISTRIBUTOR2"); + if ((*certIt)->isRootCert()) { + instCertType = PM_SET_DISTRIBUTOR2_ROOT_CERT; + } else { + if ((*certIt)->isCA()) { + instCertType = PM_SET_DISTRIBUTOR2_INTERMEDIATE_CERT; + } else { + instCertType = PM_SET_DISTRIBUTOR2_SIGNER_CERT; + } + } + } + } else { + _D("set SIGNATURE_AUTHOR"); + if ((*certIt)->isRootCert()) { + instCertType = PM_SET_AUTHOR_ROOT_CERT; + } else { + if ((*certIt)->isCA()) { + instCertType = PM_SET_AUTHOR_INTERMEDIATE_CERT; + } else { + instCertType = PM_SET_AUTHOR_SIGNER_CERT; + } + } + } + _D("cert type : %d", instCertType); + if ((pkgmgr_installer_set_cert_value( + m_pkgHandle, + instCertType, + const_cast(((*certIt)->getBase64()).c_str()))) < 0) + { + _E("pkgmgrInstallerSetCertValue fail"); + ThrowMsg(Exceptions::SetCertificateInfoFailed, + "Failed to Set CertValue"); + } + } + } +} + +void TaskPkgInfoUpdate::StepAbortCertiInfo() +{ + if ((pkgmgr_installer_delete_certinfo( + const_cast(DPL::ToUTF8String( + m_context.widgetConfig.tzPkgid).c_str()))) < + 0) + { + _E("pkgmgr_installer_delete_certinfo fail"); + } +} + +void TaskPkgInfoUpdate::StartStep() +{ + _D("--------- : START ----------"); +} + +void TaskPkgInfoUpdate::EndStep() +{ + m_context.job->UpdateProgress( + InstallerContext::INSTALL_SET_CERTINFO, + "Save certinfo to pkgmgr"); + + _D("--------- : END ----------"); +} + +void TaskPkgInfoUpdate::stepAbortParseManifest() +{ + _E("[Parse Manifest] Abroting...."); + + int code = pkgmgr_parser_parse_manifest_for_uninstallation( + m_manifest.c_str(), NULL); + + if (0 != code) { + _W("Manifest parser error: %d", code); + ThrowMsg(Exceptions::ManifestInvalid, "Parser returncode: " << code); + } + int ret = unlink(m_manifest.c_str()); + if (0 != ret) { + _W("No manifest file found: %s", m_manifest.c_str()); + } +} + +void TaskPkgInfoUpdate::StepSetEndofInstallation() +{ + m_context.job->UpdateProgress( + InstallerContext::INSTALL_END, + "End installation"); +} + +} //namespace WidgetInstall +} //namespace Jobs diff --git a/src_mobile/jobs/widget_install/task_pkg_info_update.h b/src_mobile/jobs/widget_install/task_pkg_info_update.h new file mode 100644 index 0000000..e1e9235 --- /dev/null +++ b/src_mobile/jobs/widget_install/task_pkg_info_update.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file task_pkg_info_update.h + * @author soyoung kim (sy037.kim@samsung.com) + * @version 1.0 + */ + +#ifndef SRC_JOBS_WIDGET_INSTALL_TASK_PKG_INFO_UPDATE_H_ +#define SRC_JOBS_WIDGET_INSTALL_TASK_PKG_INFO_UPDATE_H_ + +#include +#include +#include + +class InstallerContext; + +namespace Jobs { +namespace WidgetInstall { +class TaskPkgInfoUpdate : public DPL::TaskDecl +{ + private: + // Installation context + InstallerContext &m_context; + + void StepPkgInfo(); + void StepSetCertiInfo(); + void SetCertiInfo(int source); + void StepSetEndofInstallation(); + + void stepAbortParseManifest(); + void StepAbortCertiInfo(); + + void StartStep(); + void EndStep(); + + pkgmgr_instcertinfo_h m_pkgHandle; + std::string m_manifest; + + public: + explicit TaskPkgInfoUpdate(InstallerContext &installerContext); +}; +} // namespace WidgetInstall +} // namespace Jobs +#endif /* SRC_JOBS_WIDGET_INSTALL_TASK_PKG_INFO_UPDATE_H_ */ diff --git a/src_mobile/jobs/widget_install/task_prepare_files.cpp b/src_mobile/jobs/widget_install/task_prepare_files.cpp new file mode 100644 index 0000000..55791f4 --- /dev/null +++ b/src_mobile/jobs/widget_install/task_prepare_files.cpp @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file task_generate_config.cpp + * @author Krzysztof Jackiewicz (k.jackiewicz@samsung.com) + * @version 1.0 + */ + +#include "task_prepare_files.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Jobs { +namespace WidgetInstall { +TaskPrepareFiles::TaskPrepareFiles(InstallerContext &installerContext) : + DPL::TaskDecl(this), + m_installerContext(installerContext) +{ + AddStep(&TaskPrepareFiles::StartStep); + AddStep(&TaskPrepareFiles::StepCopyFiles); + AddStep(&TaskPrepareFiles::EndStep); +} + +void TaskPrepareFiles::CopyFile(const std::string& source) +{ + if (source.empty()) { + _W("No source file specified"); + return; + } + + std::string filename = source; + size_t last = source.find_last_of("\\/"); + if (last != std::string::npos) { + filename = source.substr(last + 1); + } + std::string target = + m_installerContext.locations->getSourceDir() + '/' + + filename; + _D("source %s", source.c_str()); + _D("target %s", target.c_str()); + + Try + { + DPL::FileInput input(source); + DPL::FileOutput output(target); + DPL::Copy(&input, &output); + } + Catch(DPL::FileInput::Exception::Base) + { + _E("File input error"); + // Error while opening or closing source file + ReThrowMsg(Exceptions::CopyIconFailed, source); + } + Catch(DPL::FileOutput::Exception::Base) + { + _E("File output error"); + // Error while opening or closing target file + ReThrowMsg(Exceptions::CopyIconFailed, target); + } + Catch(DPL::CopyFailed) + { + _E("File copy error"); + // Error while copying + ReThrowMsg(Exceptions::CopyIconFailed, target); + } +} + +void TaskPrepareFiles::StepCopyFiles() +{ + CopyFile(m_installerContext.locations->getWidgetSource()); + + size_t last = m_installerContext.locations->getWidgetSource().find_last_of( + "\\/"); + std::string sourceDir = ""; + if (last != std::string::npos) { + sourceDir = m_installerContext.locations->getWidgetSource().substr( + 0, + last + + 1); + } + + _D("Icons copy..."); + FOREACH(it, m_installerContext.widgetConfig.configInfo.iconsList) { + std::ostringstream os; + _D("Coping: %s%ls", sourceDir.c_str(), (it->src).c_str()); + os << sourceDir << DPL::ToUTF8String(it->src); + CopyFile(os.str()); + } +} + +void TaskPrepareFiles::StartStep() +{ + _D("--------- : START ----------"); +} + +void TaskPrepareFiles::EndStep() +{ + _D("--------- : END ----------"); +} +} // namespace WidgetInstall +} // namespace Jobs diff --git a/src_mobile/jobs/widget_install/task_prepare_files.h b/src_mobile/jobs/widget_install/task_prepare_files.h new file mode 100644 index 0000000..99458e8 --- /dev/null +++ b/src_mobile/jobs/widget_install/task_prepare_files.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file task_prepare_files.h + * @author Krzysztof Jackiewicz (k.jackiewicz@samsung.com) + * @version 1.0 + */ + +#ifndef SRC_JOBS_WIDGET_INSTALL_TASK_PREPARE_FILES_H_ +#define SRC_JOBS_WIDGET_INSTALL_TASK_PREPARE_FILES_H_ + +#include +#include + +class InstallerContext; + +namespace Jobs { +namespace WidgetInstall { +class TaskPrepareFiles : public DPL::TaskDecl +{ + private: + // Installation context + InstallerContext &m_installerContext; + + void CopyFile(const std::string& source); + + // Steps + void StepCopyFiles(); + + void StartStep(); + void EndStep(); + + public: + explicit TaskPrepareFiles(InstallerContext &installerContext); +}; +} // namespace WidgetInstall +} // namespace Jobs +#endif /* SRC_JOBS_WIDGET_INSTALL_TASK_PREPARE_FILES_H_ */ diff --git a/src_mobile/jobs/widget_install/task_prepare_reinstall.cpp b/src_mobile/jobs/widget_install/task_prepare_reinstall.cpp new file mode 100644 index 0000000..4980e4d --- /dev/null +++ b/src_mobile/jobs/widget_install/task_prepare_reinstall.cpp @@ -0,0 +1,255 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file task_prepare_reinstall.cpp + * @author Jihoon Chung(jihoon.chung@samsung.com) + * @version 1.0 + * @brief Implementation file for installer task prepare reinstalling + */ + +#include "task_prepare_reinstall.h" + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include + +namespace Jobs { +namespace WidgetInstall { +namespace { +const char* const KEY_DELETE = "#delete"; +const char* const KEY_ADD = "#add"; +const char* const KEY_MODIFY = "#modify"; +std::list keyList = {KEY_DELETE, KEY_ADD, KEY_MODIFY}; + +void verifyFile(const std::string &filePath) +{ + if (access(filePath.c_str(), F_OK) != 0) { + ThrowMsg(Exceptions::RDSDeltaFailure, "File is missed " << filePath); + } +} + +std::string parseSubPath(const std::string& filePath) +{ + std::string subPath(""); + size_t pos = filePath.find_last_of('/') + 1; + + if (pos != std::string::npos) { + subPath = filePath.substr(0, pos); + } + return subPath; +} + +void createDir(const std::string& path) +{ + if (WrtUtilMakeDir(path)) { + _D("Create directory : %s", path.c_str()); + } else { + ThrowMsg(Exceptions::RDSDeltaFailure, "Fail to create dir" << path); + } +} +} // namespace anonymous + +TaskPrepareReinstall::TaskPrepareReinstall(InstallerContext& context) : + DPL::TaskDecl(this), + m_context(context) +{ + AddStep(&TaskPrepareReinstall::StartStep); + AddStep(&TaskPrepareReinstall::StepPrepare); + AddStep(&TaskPrepareReinstall::StepParseRDSDelta); + AddStep(&TaskPrepareReinstall::StepVerifyRDSDelta); + AddStep(&TaskPrepareReinstall::StepAddFile); + AddStep(&TaskPrepareReinstall::StepDeleteFile); + AddStep(&TaskPrepareReinstall::StepModifyFile); + AddStep(&TaskPrepareReinstall::EndStep); +} + +void TaskPrepareReinstall::StepPrepare() +{ + _D("Prepare"); + m_sourcePath = m_context.locations->getTemporaryPackageDir(); + m_sourcePath += "/"; + + m_installedPath = m_context.locations->getPackageInstallationDir(); + m_installedPath += "/"; +} + +void TaskPrepareReinstall::StepParseRDSDelta() +{ + _D("parse RDS delta"); + std::string rdsDeltaPath = m_sourcePath; + rdsDeltaPath += ".rds_delta"; + std::ifstream delta(rdsDeltaPath); + + if (!delta.is_open()) { + ThrowMsg(Exceptions::RDSDeltaFailure, "rds_delta file is missed"); + return; + } + + std::string line; + std::string key; + while (std::getline(delta, line) &&!delta.eof()) { + FOREACH(keyIt, keyList) { + if (line == *keyIt) { + _D("find key = [%s]", line.c_str()); + key = line; + break; + } + } + if (key == line || line.empty() || line == "\n") { + continue; + } + if (key == KEY_DELETE) { + m_deleteFileList.push_back(line); + _D("line = [%s]", line.c_str()); + } else if (key == KEY_ADD) { + m_addFileList.push_back(line); + _D("line = [%s]", line.c_str()); + } else if (key == KEY_MODIFY) { + m_modifyFileList.push_back(line); + _D("line = [%s]", line.c_str()); + } + } +} + +void TaskPrepareReinstall::StepVerifyRDSDelta() +{ + _D("verify RDS delta"); + // Verify ADD file + FOREACH(file, m_addFileList) { + std::string addFilePath = m_sourcePath; + addFilePath += *file; + verifyFile(addFilePath); + } + // Verify DELETE file + FOREACH(file, m_deleteFileList) { + std::string deleteFilePath = m_installedPath; + deleteFilePath += *file; + verifyFile(deleteFilePath); + } + // Verify MODIFY file + FOREACH(file, m_modifyFileList) { + std::string newFilePath = m_sourcePath; + newFilePath += *file; + verifyFile(newFilePath); + + std::string existingFilePath = m_installedPath; + existingFilePath += *file; + verifyFile(existingFilePath); + } + _D("Finished veify RDS Delta"); + + m_context.job->UpdateProgress( + InstallerContext::INSTALL_RDS_DELTA_CHECK, + "RDS delta verify finished"); +} + +void TaskPrepareReinstall::StepAddFile() +{ + _D("Add file"); + FOREACH(file, m_addFileList) { + std::string newfile = m_sourcePath; + newfile += *file; + std::string destPath = m_installedPath; + destPath += *file; + + if (WrtUtilDirExists(newfile)) { + // In case of a new directory + createDir(destPath); + } else { + // In case of a new file + + // Parse directory and file separately + std::string subPath = parseSubPath(destPath); + if (subPath.empty()) { + ThrowMsg(Exceptions::RDSDeltaFailure, + "Invalid path given" << destPath); + } + + // Create a new directory + createDir(subPath); + + // Add file + if (rename(newfile.c_str(), destPath.c_str()) != 0) { + ThrowMsg(Exceptions::RDSDeltaFailure, + "Fail to add file " << newfile); + } + _D("Add %s to %s", newfile.c_str(), destPath.c_str()); + } + } +} + +void TaskPrepareReinstall::StepDeleteFile() +{ + _D("Delete file"); + FOREACH(file, m_deleteFileList) { + std::string deleteFilePath = m_installedPath; + deleteFilePath += *file; + if (remove(deleteFilePath.c_str()) != 0) { + ThrowMsg(Exceptions::RDSDeltaFailure, + "Fail to DELETE file " << deleteFilePath); + } + _D("Delete %s", deleteFilePath.c_str()); + } +} + +void TaskPrepareReinstall::StepModifyFile() +{ + _D("Modify file"); + FOREACH(file, m_modifyFileList) { + std::string destPath = m_installedPath; + destPath += *file; + if (remove(destPath.c_str()) != 0) { + ThrowMsg(Exceptions::RDSDeltaFailure, + "Fail to delete existing file " << destPath); + } + + std::string newfile = m_sourcePath; + newfile += *file; + if (rename(newfile.c_str(), destPath.c_str()) != 0) { + ThrowMsg(Exceptions::RDSDeltaFailure, + "Fail to move new file" << destPath); + } + _D("Replace %s to %s", newfile.c_str(), destPath.c_str()); + } +} + +void TaskPrepareReinstall::StartStep() +{ + _D("---------- : START ----------"); +} + +void TaskPrepareReinstall::EndStep() +{ + m_context.job->UpdateProgress( + InstallerContext::INSTALL_RDS_PREPARE, + "RDS prepare finished"); + + _D("---------- : END ----------"); +} + +} //namespace WidgetInstall +} //namespace Jobs diff --git a/src_mobile/jobs/widget_install/task_prepare_reinstall.h b/src_mobile/jobs/widget_install/task_prepare_reinstall.h new file mode 100644 index 0000000..2828f27 --- /dev/null +++ b/src_mobile/jobs/widget_install/task_prepare_reinstall.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file task_prepare_reinstall.h + * @author Jihoon Chung(jihoon.chung@samsung.com) + * @version 1.0 + * @brief Header file for installer task prepare reinstalling + */ +#ifndef INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_PREPARE_REINSTALL_H +#define INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_PREPARE_REINSTALL_H + +#include +#include + +#include + +class InstallerContext; + +namespace Jobs { +namespace WidgetInstall { +class TaskPrepareReinstall : + public DPL::TaskDecl +{ + public: + TaskPrepareReinstall(InstallerContext& context); + + private: + // install internal location + void StepPrepare(); + void StepParseRDSDelta(); + void StepVerifyRDSDelta(); + void StepAddFile(); + void StepDeleteFile(); + void StepModifyFile(); + + void StepAbortPrepareReinstall(); + + void StartStep(); + void EndStep(); + + InstallerContext& m_context; + // TODO : replace multimap + std::list m_addFileList; + std::list m_deleteFileList; + std::list m_modifyFileList; + std::string m_sourcePath; + std::string m_installedPath; +}; +} //namespace WidgetInstall +} //namespace Jobs + +#endif // INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_PREPARE_REINSTALL_H diff --git a/src_mobile/jobs/widget_install/task_process_config.cpp b/src_mobile/jobs/widget_install/task_process_config.cpp new file mode 100755 index 0000000..2c92f2c --- /dev/null +++ b/src_mobile/jobs/widget_install/task_process_config.cpp @@ -0,0 +1,681 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file task_process_config.cpp + * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com) + * @version 1.0 + * @brief Implementation file for installer task widget config + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace { // anonymous +const DPL::String BR = DPL::FromUTF8String("
"); +const std::string WINDGET_INSTALL_NETWORK_ACCESS = "network access"; +} + +namespace Jobs { +namespace WidgetInstall { + +TaskProcessConfig::TaskProcessConfig(InstallerContext& installContext) : + DPL::TaskDecl(this), + m_installContext(installContext) +{ + AddStep(&TaskProcessConfig::StartStep); + AddStep(&TaskProcessConfig::ReadLocaleFolders); + AddStep(&TaskProcessConfig::StepFillWidgetConfig); + AddStep(&TaskProcessConfig::ProcessLocalizedStartFiles); + AddStep(&TaskProcessConfig::ProcessBackgroundPageFile); + AddStep(&TaskProcessConfig::ProcessLocalizedIcons); + AddStep(&TaskProcessConfig::ProcessWidgetInstalledPath); + AddStep(&TaskProcessConfig::ProcessAppControlInfo); + AddStep(&TaskProcessConfig::ProcessSecurityModel); + AddStep(&TaskProcessConfig::StepVerifyFeatures); + AddStep(&TaskProcessConfig::StepVerifyLivebox); + AddStep(&TaskProcessConfig::StepCheckMinVersionInfo); + AddStep(&TaskProcessConfig::EndStep); +} + +void TaskProcessConfig::StepFillWidgetConfig() +{ + if (!fillWidgetConfig(m_installContext.widgetConfig, + m_installContext.widgetConfig.configInfo)) + { + _E("Widget configuration is illformed"); + ThrowMsg(Exception::ConfigParseFailed, "Widget configuration is illformed"); + } +} + +void TaskProcessConfig::ReadLocaleFolders() +{ + _D("Reading locale"); + //Adding default locale + m_localeFolders.insert(L""); + + std::string localePath = + m_installContext.locations->getSourceDir() + "/locales"; + + DIR* localeDir = opendir(localePath.c_str()); + if (!localeDir) { + _D("No /locales directory in the widget package."); + return; + } + + struct stat statStruct; + struct dirent dirent; + struct dirent *result; + int return_code; + errno = 0; + for (return_code = readdir_r(localeDir, &dirent, &result); + result != NULL && return_code == 0; + return_code = readdir_r(localeDir, &dirent, &result)) + { + DPL::String dirName = DPL::FromUTF8String(dirent.d_name); + std::string absoluteDirName = localePath + "/"; + absoluteDirName += dirent.d_name; + + if (stat(absoluteDirName.c_str(), &statStruct) != 0) { + _E("stat() failed with %s", DPL::GetErrnoString().c_str()); + continue; + } + + if (S_ISDIR(statStruct.st_mode)) { + //Yes, we ignore current, parent & hidden directories + if (dirName[0] != L'.') { + _D("Adding locale directory \"%ls\"", dirName.c_str()); + m_localeFolders.insert(dirName); + } + } + } + + if (return_code != 0 || errno != 0) { + _E("readdir_r() failed with %s", DPL::GetErrnoString().c_str()); + } + + if (-1 == closedir(localeDir)) { + _E("Failed to close dir: %s with error: %s", localePath.c_str(), DPL::GetErrnoString().c_str()); + } + + m_installContext.job->UpdateProgress(InstallerContext::INSTALL_WIDGET_CONFIG1, "Read locale folders"); +} + +void TaskProcessConfig::ProcessLocalizedStartFiles() +{ + typedef DPL::String S; + ProcessStartFile( + m_installContext.widgetConfig.configInfo.startFile, + m_installContext.widgetConfig.configInfo. + startFileContentType, + m_installContext.widgetConfig.configInfo.startFileEncoding, + true); + ProcessStartFile(S(L"index.htm"), S(L"text/html")); + ProcessStartFile(S(L"index.html"), S(L"text/html")); + ProcessStartFile(S(L"index.svg"), S(L"image/svg+xml")); + ProcessStartFile(S(L"index.xhtml"), S(L"application/xhtml+xml")); + ProcessStartFile(S(L"index.xht"), S(L"application/xhtml+xml")); + // TODO: we need better check if in current locales widget is valid + FOREACH(it, m_installContext.widgetConfig.localizationData.startFiles) { + if (it->propertiesForLocales.size() > 0) { + return; + } + } + ThrowMsg(Exceptions::InvalidStartFile, + "The Widget has no valid start file"); +} + +void TaskProcessConfig::ProcessStartFile(const DPL::OptionalString& path, + const DPL::OptionalString& type, + const DPL::OptionalString& encoding, + bool typeForcedInConfig) +{ + using namespace WrtDB; + + if (!!path) { + WidgetRegisterInfo::LocalizedStartFile startFileData; + startFileData.path = *path; + + FOREACH(i, m_localeFolders) { + DPL::String pathPrefix = *i; + if (!pathPrefix.empty()) { + pathPrefix = L"locales/" + pathPrefix + L"/"; + } + + DPL::String relativePath = pathPrefix + *path; + DPL::String absolutePath = DPL::FromUTF8String( + m_installContext.locations->getSourceDir()) + L"/" + + relativePath; + _D("absolutePath : %ls", absolutePath.c_str()); + + // get property data from packaged app + if (WrtUtilFileExists(DPL::ToUTF8String(absolutePath))) { + WidgetRegisterInfo::StartFileProperties startFileProperties; + if (!!type) { + startFileProperties.type = *type; + } else { + startFileProperties.type = + MimeTypeUtils::identifyFileMimeType(absolutePath); + } + + //proceed only if MIME type is supported + if (MimeTypeUtils::isMimeTypeSupportedForStartFile( + startFileProperties.type)) + { + if (!!encoding) { + startFileProperties.encoding = *encoding; + } else { + MimeTypeUtils::MimeAttributes attributes = + MimeTypeUtils::getMimeAttributes( + startFileProperties.type); + if (attributes.count(L"charset") > 0) { + startFileProperties.encoding = + attributes[L"charset"]; + } else { + startFileProperties.encoding = L"UTF-8"; + } + } + + startFileData.propertiesForLocales[*i] = + startFileProperties; + } else { + //9.1.16.5.content.8 + //(there seems to be no similar requirement in .6, + //so let's throw only when mime type is + // provided explcitly in config.xml) + if (typeForcedInConfig) { + ThrowMsg(Exceptions::WidgetConfigFileInvalid, + "Unsupported MIME type for start file."); + } + } + } else { + // set property data for hosted start url + // Hosted start url only support TIZEN WebApp + if (m_installContext.widgetConfig.webAppType == + APP_TYPE_TIZENWEBAPP) + { + std::string startPath = DPL::ToUTF8String( + startFileData.path); + + if (strstr(startPath.c_str(), + "http") == startPath.c_str()) + { + WidgetRegisterInfo::StartFileProperties + startFileProperties; + if (!!type) { + startFileProperties.type = *type; + } + if (!!encoding) { + startFileProperties.encoding = *encoding; + } + startFileData.propertiesForLocales[*i] = + startFileProperties; + } + } + } + } + + m_installContext.widgetConfig.localizationData.startFiles.push_back( + startFileData); + } +} + +void TaskProcessConfig::ProcessBackgroundPageFile() +{ + if (!!m_installContext.widgetConfig.configInfo.backgroundPage) { + // check whether file exists + DPL::String backgroundPagePath = DPL::FromUTF8String( + m_installContext.locations->getSourceDir()) + L"/" + + *m_installContext.widgetConfig.configInfo.backgroundPage; + //if no then cancel installation + if (!WrtUtilFileExists(DPL::ToUTF8String(backgroundPagePath))) { + ThrowMsg(Exceptions::WidgetConfigFileInvalid, + L"Given background page file not found in archive"); + } + } +} + +void TaskProcessConfig::ProcessLocalizedIcons() +{ + using namespace WrtDB; + FOREACH(i, m_installContext.widgetConfig.configInfo.iconsList) + { + ProcessIcon(*i); + } + ProcessIcon(ConfigParserData::Icon(L"icon.svg")); + ProcessIcon(ConfigParserData::Icon(L"icon.ico")); + ProcessIcon(ConfigParserData::Icon(L"icon.png")); + ProcessIcon(ConfigParserData::Icon(L"icon.gif")); + ProcessIcon(ConfigParserData::Icon(L"icon.jpg")); +} + +void TaskProcessConfig::ProcessIcon(const WrtDB::ConfigParserData::Icon& icon) +{ + _D("enter"); + bool isAnyIconValid = false; + //In case a default filename is passed as custom filename in config.xml, we + //need to keep a set of already processed filenames to avoid icon + // duplication + //in database. + + using namespace WrtDB; + + if (m_processedIconSet.count(icon.src) > 0) { + return; + } + m_processedIconSet.insert(icon.src); + + LocaleSet localesAvailableForIcon; + + FOREACH(i, m_localeFolders) + { + DPL::String pathPrefix = *i; + if (!pathPrefix.empty()) { + pathPrefix = L"locales/" + pathPrefix + L"/"; + } + + DPL::String relativePath = pathPrefix + icon.src; + DPL::String absolutePath = DPL::FromUTF8String( + m_installContext.locations->getSourceDir()) + L"/" + + relativePath; + + if (WrtUtilFileExists(DPL::ToUTF8String(absolutePath))) { + DPL::String type = MimeTypeUtils::identifyFileMimeType(absolutePath); + + if (MimeTypeUtils::isMimeTypeSupportedForIcon(type)) { + isAnyIconValid = true; + localesAvailableForIcon.insert(*i); + _D("Icon absolutePath: %ls, assigned locale: %ls, type: %ls", + absolutePath.c_str(), (*i).c_str(), type.c_str()); + } + } + } + + if (isAnyIconValid) { + WidgetRegisterInfo::LocalizedIcon localizedIcon(icon, + localesAvailableForIcon); + m_installContext.widgetConfig.localizationData.icons.push_back( + localizedIcon); + } +} + +void TaskProcessConfig::ProcessWidgetInstalledPath() +{ + _D("ProcessWidgetInstalledPath"); + m_installContext.widgetConfig.widgetInstalledPath = + DPL::FromUTF8String( + m_installContext.locations->getPackageInstallationDir()); +} + +void TaskProcessConfig::ProcessAppControlInfo() +{ + _D("ProcessAppControlInfo"); + using namespace WrtDB; + + // In case of dispostion is inline, set the seperate execute + int index = 1; + // 0 index is reserved by default execute + FOREACH(it, m_installContext.widgetConfig.configInfo.appControlList) { + if (it->m_disposition == + ConfigParserData::AppControlInfo::Disposition::INLINE) + { + it->m_index = index++; + } else { + it->m_index = 0; + } + } +} + +void TaskProcessConfig::ProcessSecurityModel() +{ + // 0104. If the "required_version" specified in the Web Application's + // configuration is 2.2 or higher and if the Web Application's + // configuration is "CSP-compatible configuration", then the WRT MUST be + // set to "CSP-based security mode". Otherwise, the WRT MUST be set to + // "WARP-based security mode". + // 0105. A Web Application configuration is "CSP-compatible configuration" + // if the configuration includes one or more of + // / + // / + // elements. + + bool isSecurityModelV1 = false; + bool isSecurityModelV2 = false; + WrtDB::ConfigParserData &data = m_installContext.widgetConfig.configInfo; + + if (!data.cspPolicy.IsNull() || + !data.cspPolicyReportOnly.IsNull() || + !data.allowNavigationInfoList.empty()) + { + data.accessInfoSet.clear(); + } + + // WARP is V1 + if (!data.accessInfoSet.empty()) { + isSecurityModelV1 = true; + } + + // CSP & allow-navigation is V2 + if (!data.cspPolicy.IsNull() || + !data.cspPolicyReportOnly.IsNull() || + !data.allowNavigationInfoList.empty()) + { + isSecurityModelV2 = true; + } + + if (isSecurityModelV1 && isSecurityModelV2) { + _E("Security model is conflict"); + ThrowMsg(Exceptions::NotAllowed, "Security model is conflict"); + } else if (isSecurityModelV1) { + data.securityModelVersion = + WrtDB::ConfigParserData::SecurityModelVersion::SECURITY_MODEL_V1; + } else if (isSecurityModelV2) { + data.securityModelVersion = + WrtDB::ConfigParserData::SecurityModelVersion::SECURITY_MODEL_V2; + } else { + data.securityModelVersion = + WrtDB::ConfigParserData::SecurityModelVersion::SECURITY_MODEL_V1; + } + + m_installContext.job->UpdateProgress( + InstallerContext::INSTALL_WIDGET_CONFIG2, + "Finished process security model"); +} + +void TaskProcessConfig::StepCheckMinVersionInfo() +{ + if (!isMinVersionCompatible( + m_installContext.widgetConfig.webAppType.appType, + m_installContext.widgetConfig.minVersion)) + { + _E("Platform version lower than required -> cancelling installation"); + ThrowMsg(Exceptions::NotAllowed, + "Platform version does not meet requirements"); + } + + m_installContext.job->UpdateProgress( + InstallerContext::INSTALL_WIDGET_CONFIG2, + "Check MinVersion Finished"); +} + +void TaskProcessConfig::StepVerifyFeatures() +{ + using namespace WrtDB; + ConfigParserData &data = m_installContext.widgetConfig.configInfo; + ConfigParserData::FeaturesList list = data.featuresList; + ConfigParserData::FeaturesList newList; + + //in case of tests, this variable is unused + std::string featureInfo; + FOREACH(it, list) + { + // check feature vender for permission + // WAC, TIZEN WebApp cannot use other feature + + if (!isFeatureAllowed(m_installContext.widgetConfig.webAppType.appType, + it->name)) + { + _D("This application type not allowed to use this feature"); + ThrowMsg( + Exceptions::WidgetConfigFileInvalid, + "This app type [" << + m_installContext.widgetConfig.webAppType.getApptypeToString() + << + "] cannot be allowed to use [" << + DPL::ToUTF8String(it->name) + "] feature"); + } else { + newList.insert(*it); + featureInfo += DPL::ToUTF8String(it->name); + featureInfo += DPL::ToUTF8String(BR); + } + } + if (!data.accessInfoSet.empty()) { + featureInfo += WINDGET_INSTALL_NETWORK_ACCESS; + featureInfo += DPL::ToUTF8String(BR); + } + data.featuresList = newList; + + m_installContext.job->UpdateProgress( + InstallerContext::INSTALL_WIDGET_CONFIG2, + "Widget Config step2 Finished"); +} + +void TaskProcessConfig::StepVerifyLivebox() +{ + using namespace WrtDB; + ConfigParserData &data = m_installContext.widgetConfig.configInfo; + ConfigParserData::LiveboxList liveBoxList = data.m_livebox; + + if (liveBoxList.size() <= 0) { + return; + } + + FOREACH (it, liveBoxList) { + std::string boxType; + + if ((**it).m_liveboxId.find(m_installContext.widgetConfig.tzAppid) != 0) { + _E("Invalid app-widget id (doesn't begin with application id)"); + ThrowMsg(Exceptions::WidgetConfigFileInvalid, "Invalid app-widget id (doesn't begin with application id)"); + } + + if ((**it).m_type.empty()) { + boxType = web_provider_livebox_get_default_type(); + } else { + boxType = DPL::ToUTF8String((**it).m_type); + } + + _D("livebox type: %s", boxType.c_str()); + + ConfigParserData::LiveboxInfo::BoxSizeList boxSizeList = + (**it).m_boxInfo.m_boxSize; + char** boxSize = static_cast( + malloc(sizeof(char*)* boxSizeList.size())); + + int boxSizeCnt = 0; + FOREACH (m, boxSizeList) { + boxSize[boxSizeCnt++] = strdup(DPL::ToUTF8String((*m).m_size).c_str()); + } + + bool chkSize = web_provider_plugin_check_supported_size( + boxType.c_str(), boxSize, boxSizeCnt); + + for(int i = 0; i < boxSizeCnt; i++) { + free(boxSize[i]); + } + free(boxSize); + + if(!chkSize) { + _E("Invalid boxSize"); + ThrowMsg(Exceptions::WidgetConfigFileInvalid, "Invalid boxSize"); + } + } +} + +bool TaskProcessConfig::isFeatureAllowed(WrtDB::AppType appType, + DPL::String featureName) +{ + using namespace WrtDB; + _D("AppType = [%s]", WidgetType(appType).getApptypeToString().c_str()); + _D("FetureName = [%ls]", featureName.c_str()); + + AppType featureType = APP_TYPE_UNKNOWN; + std::string featureStr = DPL::ToUTF8String(featureName); + const char* feature = featureStr.c_str(); + + // check prefix of feature name + if (strstr(feature, PluginsPrefix::TIZENPluginsPrefix) == feature) { + // Tizen WebApp feature + featureType = APP_TYPE_TIZENWEBAPP; + } else if (strstr(feature, PluginsPrefix::W3CPluginsPrefix) == feature) { + // W3C standard feature + // Both WAC and TIZEN WebApp are possible to use W3C plugins + return true; + } else { + // unknown feature + // unknown feature will be checked next step + return true; + } + + if (appType == featureType) { + return true; + } + return false; +} + +bool TaskProcessConfig::parseVersionString(const std::string &version, + long &majorVersion, + long &minorVersion, + long µVersion) const +{ + std::istringstream inputString(version); + inputString >> majorVersion; + if (inputString.bad() || inputString.fail()) { + _W("Invalid minVersion format."); + return false; + } + inputString.get(); // skip period + inputString >> minorVersion; + if (inputString.bad() || inputString.fail()) { + _W("Invalid minVersion format"); + return false; + } else { + inputString.get(); // skip period + if (inputString.bad() || inputString.fail()) { + inputString >> microVersion; + } + } + return true; +} + +bool TaskProcessConfig::isMinVersionCompatible( + WrtDB::AppType appType, + const DPL::OptionalString & + widgetVersion) const +{ + if (widgetVersion.IsNull() || (*widgetVersion).empty()) { + if (appType == WrtDB::AppType::APP_TYPE_TIZENWEBAPP) { + return false; + } else { + _W("minVersion attribute is empty. WRT assumes platform " + "supports this widget."); + return true; + } + } + + //Parse widget version + long majorWidget = 0, minorWidget = 0, microWidget = 0; + if (!parseVersionString(DPL::ToUTF8String(*widgetVersion), majorWidget, + minorWidget, microWidget)) + { + _W("Invalid format of widget version string."); + return false; + } + + //Parse supported version + long majorSupported = 0, minorSupported = 0, microSupported = 0; + std::string version; + if (appType == WrtDB::AppType::APP_TYPE_TIZENWEBAPP) { + version = WrtDB::GlobalConfig::GetTizenVersion(); + } else { + _W("Invaild AppType"); + return false; + } + + if (!parseVersionString(version, + majorSupported, minorSupported, microSupported)) + { + _W("Invalid format of platform version string."); + return true; + } + + if (majorWidget > majorSupported || + (majorWidget == majorSupported && minorWidget > minorSupported) || + (majorWidget == majorSupported && minorWidget == minorSupported + && microWidget > microSupported)) + { + _D("Platform doesn't support this widget."); + return false; + } + return true; +} + +bool TaskProcessConfig::isTizenWebApp() const +{ + if (m_installContext.widgetConfig.webAppType.appType == WrtDB::AppType::APP_TYPE_TIZENWEBAPP) + { + return true; + } + return false; +} + +bool TaskProcessConfig::fillWidgetConfig( + WrtDB::WidgetRegisterInfo& pWidgetConfigInfo, + WrtDB::ConfigParserData& configInfo) +{ + pWidgetConfigInfo.guid = configInfo.widget_id; + + if (!!configInfo.version) { + if (!pWidgetConfigInfo.version) { + pWidgetConfigInfo.version = configInfo.version; + } else { + if (pWidgetConfigInfo.version != configInfo.version) { + _E("Invalid archive"); + return false; + } + } + } + if (!!configInfo.minVersionRequired) { + pWidgetConfigInfo.minVersion = configInfo.minVersionRequired; + } else if (!!configInfo.tizenMinVersionRequired) { + pWidgetConfigInfo.minVersion = configInfo.tizenMinVersionRequired; + } + return true; +} + +void TaskProcessConfig::StartStep() +{ + _D("--------- : START ----------"); +} + +void TaskProcessConfig::EndStep() +{ + _D("--------- : END ----------"); +} + +} //namespace WidgetInstall +} //namespace Jobs diff --git a/src_mobile/jobs/widget_install/task_process_config.h b/src_mobile/jobs/widget_install/task_process_config.h new file mode 100755 index 0000000..8d844d6 --- /dev/null +++ b/src_mobile/jobs/widget_install/task_process_config.h @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file task_process_config.h + * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com) + * @version 1.0 + * @brief Implementation file for installer task widget config + */ +#ifndef INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_PROCESS_CONFIG_H +#define INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_PROCESS_CONFIG_H + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +class InstallerContext; + +namespace Jobs { +namespace WidgetInstall { + +class TaskProcessConfig : + public DPL::TaskDecl +{ + private: + class Exception + { + public: + DECLARE_EXCEPTION_TYPE(DPL::Exception, Base) + DECLARE_EXCEPTION_TYPE(Base, ConfigParseFailed) + }; + + typedef std::list > StringPairList; + + InstallerContext& m_installContext; + WrtDB::LocaleSet m_localeFolders; + std::set m_processedIconSet; + + void StepFillWidgetConfig(); + void ReadLocaleFolders(); + void ProcessLocalizedStartFiles(); + void ProcessStartFile( + const DPL::OptionalString& path, + const DPL::OptionalString& type, + const DPL::OptionalString& encoding = + DPL::OptionalString::Null, + bool typeForcedInConfig = false); + void ProcessBackgroundPageFile(); + void ProcessLocalizedIcons(); + void ProcessIcon(const WrtDB::ConfigParserData::Icon& icon); + void ProcessWidgetInstalledPath(); + void ProcessAppControlInfo(); + void ProcessSecurityModel(); + void StepVerifyFeatures(); + void StepVerifyLivebox(); + void StepCheckMinVersionInfo(); + + template + void StepCancelInstallation(); + + void StartStep(); + void EndStep(); + + DPL::String createAuthorWidgetInfo() const; + bool isFeatureAllowed( + WrtDB::AppType appType, DPL::String featureName); + bool isMinVersionCompatible( + WrtDB::AppType appType, + const DPL::OptionalString &widgetVersion) const; + /** + * @brief Parses version string in format "major.minor.micro anything" + * Returns false if format is invalid + */ + bool isTizenWebApp() const; + bool parseVersionString(const std::string &version, long &majorVersion, + long &minorVersion, long µVersion) const; + + bool fillWidgetConfig(WrtDB::WidgetRegisterInfo& pWidgetConfigInfo, + WrtDB::ConfigParserData& configInfo); + + public: + TaskProcessConfig(InstallerContext& installTaskContext); +}; +} //namespace WidgetInstall +} //namespace Jobs + +#endif // INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_PROCESS_CONFIG_H diff --git a/src_mobile/jobs/widget_install/task_recovery.cpp b/src_mobile/jobs/widget_install/task_recovery.cpp new file mode 100644 index 0000000..cf9d952 --- /dev/null +++ b/src_mobile/jobs/widget_install/task_recovery.cpp @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file task_recovery.cpp + * @author Soyoung Kim (sy037.kim@samsung.com) + * @version 1.0 + * @brief Implementation file for installer task recovery + */ +#include "task_recovery.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include + +using namespace WrtDB; + +namespace Jobs { +namespace WidgetInstall { +TaskRecovery::TaskRecovery(InstallerContext& context) : + DPL::TaskDecl(this), + m_context(context) +{ + AddStep(&TaskRecovery::StartStep); + AddStep(&TaskRecovery::StepCreateCheckFile); + AddStep(&TaskRecovery::EndStep); +} + +void TaskRecovery::StartStep() +{ + _D("---------- : START ----------"); +} + +void TaskRecovery::EndStep() +{ + m_context.job->UpdateProgress( + InstallerContext::INSTALL_CHECK_FILE, + "Create information file for recovery"); + + _D("---------- : END ----------"); +} + +void TaskRecovery::StepCreateCheckFile() +{ + _D("Step: create information file for recovery"); + + size_t pos = m_context.locations->getWidgetSource().rfind("/"); + std::ostringstream infoPath; + infoPath << GlobalConfig::GetTempInstallInfoPath(); + infoPath << "/"; + infoPath << m_context.locations->getWidgetSource().substr(pos + 1); + + FILE *temp = fopen(infoPath.str().c_str(), "w+"); + if (temp != NULL) { + fputs(m_context.locations->getWidgetSource().c_str(), temp); + int ret = fsync(temp->_fileno); + fclose(temp); + if (-1 == ret) { + ThrowMsg(Exceptions::FileOperationFailed, "Fail to fsync for recovery."); + } + + m_context.installInfo = infoPath.str(); + + _D("Create file : %s", m_context.installInfo.c_str()); + } else { + ThrowMsg(Exceptions::FileOperationFailed, "Fail to create file for recovery."); + } +} +} //namespace WidgetInstall +} //namespace Jobs diff --git a/src_mobile/jobs/widget_install/task_recovery.h b/src_mobile/jobs/widget_install/task_recovery.h new file mode 100644 index 0000000..22503a3 --- /dev/null +++ b/src_mobile/jobs/widget_install/task_recovery.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file task_recovery.h + * @author soyoung kim (sy037.kim@samsung.com) + * @version 1.0 + */ + +#ifndef SRC_JOBS_WIDGET_INSTALL_TASK_RECOVERY_FILES_H_ +#define SRC_JOBS_WIDGET_INSTALL_TASK_RECOVERY_FILES_H_ + +#include +#include + +class InstallerContext; + +namespace Jobs { +namespace WidgetInstall { +class TaskRecovery : public DPL::TaskDecl +{ + private: + // Installation context + InstallerContext &m_context; + + void StepCreateCheckFile(); + void StartStep(); + void EndStep(); + + public: + explicit TaskRecovery(InstallerContext &installerContext); +}; +} // namespace WidgetInstall +} // namespace Jobs +#endif /* SRC_JOBS_WIDGET_INSTALL_TASK_RECOVERY_FILES_H_ */ diff --git a/src_mobile/jobs/widget_install/task_remove_backup.cpp b/src_mobile/jobs/widget_install/task_remove_backup.cpp new file mode 100644 index 0000000..10caf9e --- /dev/null +++ b/src_mobile/jobs/widget_install/task_remove_backup.cpp @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file task_remove_backup.cpp + * @author Soyoung kim(sy037.kim@samsung.com) + * @version 1.0 + * @brief Implementation file for installer task backup files remove + */ +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace WrtDB; + +namespace Jobs { +namespace WidgetInstall { +TaskRemoveBackupFiles::TaskRemoveBackupFiles(InstallerContext& context) : + DPL::TaskDecl(this), + m_context(context) +{ + AddStep(&TaskRemoveBackupFiles::StartStep); + if (m_context.mode.extension != InstallMode::ExtensionType::DIR) + { + AddStep(&TaskRemoveBackupFiles::StepRemoveBackupFiles); + } + AddStep(&TaskRemoveBackupFiles::StepDeleteBackupDB); + AddStep(&TaskRemoveBackupFiles::StepDeleteBackupWidgetInterfaceDB); + AddStep(&TaskRemoveBackupFiles::EndStep); +} + +void TaskRemoveBackupFiles::StepRemoveBackupFiles() +{ + std::ostringstream backupDir; + backupDir << m_context.locations->getBackupDir(); + + if (WrtUtilRemove(backupDir.str())) { + _D("Success to remove backup files : %s", backupDir.str().c_str()); + } else { + _E("Failed to remove backup directory : %s", backupDir.str().c_str()); + ThrowMsg(Exceptions::RemoveBackupFailed, + "Error occurs during removing existing folder"); + } + + std::string tmp = m_context.locations->getTemporaryPackageDir(); + if (WrtUtilRemove(tmp)) { + _D("Success to remove temp directory : %s", tmp.c_str()); + } else { + _E("Failed to remove temp directory : %s", tmp.c_str()); + } +} + +void TaskRemoveBackupFiles::StepDeleteBackupDB() +{ + _D("StepDeleteBackupDB"); + std::string oldAppid = + DPL::ToUTF8String(m_context.widgetConfig.tzAppid) + ".backup"; + + Try + { + WidgetDAO::unregisterWidget(DPL::FromUTF8String(oldAppid)); + } + Catch(WidgetDAOReadOnly::Exception::WidgetNotExist) + { + _E("Fail to delete old version db information"); + } +} + +void TaskRemoveBackupFiles::StepDeleteBackupWidgetInterfaceDB() +{ + _D("StepDeleteBackupWidgetInterfaceDB"); + using namespace WidgetInterfaceDB; + using namespace WrtDB; + + DbWidgetHandle handle = + WidgetDAOReadOnly::getHandle(m_context.widgetConfig.tzAppid); + std::string backupDbPath = WidgetInterfaceDAO::databaseFileName(handle); + backupDbPath += GlobalConfig::GetBackupDatabaseSuffix(); + + // remove backup database + if (remove(backupDbPath.c_str()) != 0) { + _W("Fail to remove"); + } +} + +void TaskRemoveBackupFiles::StartStep() +{ + _D("--------- : START ----------"); +} + +void TaskRemoveBackupFiles::EndStep() +{ + _D("--------- : END ----------"); +} +} //namespace WidgetInstall +} //namespace Jobs diff --git a/src_mobile/jobs/widget_install/task_remove_backup.h b/src_mobile/jobs/widget_install/task_remove_backup.h new file mode 100644 index 0000000..1dcdf5b --- /dev/null +++ b/src_mobile/jobs/widget_install/task_remove_backup.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file task_remove_backup.h + * @author Soyoung kim(sy037.kim@samsung.com) + * @version 1.0 + * @brief Header file for installer task backup files remove + */ +#ifndef INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_REMOVE_BACKUP_FILES_H +#define INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_REMOVE_BACKUP_FILES_H + +#include + +class InstallerContext; + +namespace Jobs { +namespace WidgetInstall { +class TaskRemoveBackupFiles : + public DPL::TaskDecl +{ + private: + InstallerContext& m_context; + + void StepRemoveBackupFiles(); + void StepDeleteBackupDB(); + void StepDeleteBackupWidgetInterfaceDB(); + + void StartStep(); + void EndStep(); + + public: + TaskRemoveBackupFiles(InstallerContext& context); +}; +} //namespace WidgetInstall +} //namespace Jobs + +#endif // INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_REMOVE_BACKUP_FILES_H diff --git a/src_mobile/jobs/widget_install/task_smack.cpp b/src_mobile/jobs/widget_install/task_smack.cpp new file mode 100644 index 0000000..0114c4e --- /dev/null +++ b/src_mobile/jobs/widget_install/task_smack.cpp @@ -0,0 +1,310 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file task_smack.cpp + * @author Piotr Kozbial (p.kozbial@samsung.com) + * @version 1.0 + * @brief Implementation file for installer task smack + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef WRT_SMACK_ENABLED +#include +#include +#endif +#include +#include +#include + +using namespace WrtDB; +using namespace ValidationCore; + +namespace { +const int MAX_BUF_SIZE = 128; +void freeList(const char** list) { + for (int i = 0; list[i] != NULL; i++) + { + delete(list[i]); + } + delete[] list; +} +} + +namespace Jobs { +namespace WidgetInstall { +TaskSmack::TaskSmack(InstallerContext& context) : + DPL::TaskDecl(this), + m_context(context), + m_pkgId(NULL) +{ + AddStep(&TaskSmack::StartStep); + AddStep(&TaskSmack::StepSetInstall); + AddStep(&TaskSmack::StepSmackFolderLabeling); + AddStep(&TaskSmack::StepSmackPrivilege); + AddStep(&TaskSmack::StepAddLabelNPRuntime); + AddStep(&TaskSmack::EndStep); + + AddAbortStep(&TaskSmack::StepAbortSmack); +} + +void TaskSmack::StepSetInstall() +{ + _D("----------------> SMACK: StepStartSetSmack()"); +#ifdef WRT_SMACK_ENABLED + std::string pkg = DPL::ToUTF8String(m_context.widgetConfig.tzPkgid); + m_pkgId = (char*)calloc(1, pkg.length() + 1); + snprintf(m_pkgId, pkg.length() + 1, "%s", pkg.c_str()); + + if (m_context.widgetConfig.packagingType != + WrtDB::PkgType::PKG_TYPE_HYBRID_WEB_APP) + { + if (PC_OPERATION_SUCCESS != perm_app_install(m_pkgId)) { + free(m_pkgId); + ThrowMsg(Exceptions::NotAllowed, "Instalation failure. " + "failure in creating smack rules file."); + } + } +#endif +} + +void TaskSmack::StepSmackFolderLabeling() +{ + _D("----------------> SMACK:\ + Jobs::WidgetInstall::TaskSmack::SmackFolderLabelingStep()"); +#ifdef WRT_SMACK_ENABLED + /* /opt/usr/apps/[pkgid] directory's label is "_" */ + if (PC_OPERATION_SUCCESS != perm_app_setup_path(m_pkgId, + m_context.locations->getPackageInstallationDir().c_str(), + APP_PATH_ANY_LABEL, "_")) { + _W("Add label to %s", m_context.locations->getPackageInstallationDir().c_str()); + } + + /* for prelaod */ + if (m_context.mode.installTime == InstallMode::InstallTime::PRELOAD && + m_context.mode.extension != InstallMode::ExtensionType::DIR) + { + if (PC_OPERATION_SUCCESS != perm_app_setup_path(m_pkgId, + m_context.locations->getUserDataRootDir().c_str(), + APP_PATH_ANY_LABEL, "_")) { + } + } + + /* res directory */ + std::string resDir = m_context.locations->getPackageInstallationDir() + + "/res"; + + if (PC_OPERATION_SUCCESS != perm_app_setup_path(m_pkgId, resDir.c_str(), + APP_PATH_PRIVATE)) { + _W("Add label to %s", resDir.c_str()); + } + + /* data directory */ + if (PC_OPERATION_SUCCESS != perm_app_setup_path(m_pkgId, + m_context.locations->getPrivateStorageDir().c_str(), + APP_PATH_PRIVATE)) { + _W("Add label to %s", m_context.locations->getPrivateStorageDir().c_str()); + } + + /* tmp directory */ + if (PC_OPERATION_SUCCESS != perm_app_setup_path(m_pkgId, + m_context.locations->getPrivateTempStorageDir().c_str(), + APP_PATH_PRIVATE)) + { + _W("Add label to %s", m_context.locations->getPrivateTempStorageDir().c_str()); + } + + /* bin directory */ + if (PC_OPERATION_SUCCESS != perm_app_setup_path(m_pkgId, + m_context.locations->getBinaryDir().c_str(), + APP_PATH_PRIVATE)) { + _W("Add label to %s", m_context.locations->getBinaryDir().c_str()); + } + + if(!setLabelForSharedDir(m_pkgId)) { + _W("Add label to shared directory"); + } + + free(m_pkgId); + + /* TODO : set label at wrt-client */ +#endif +} + +void TaskSmack::StepSmackPrivilege() +{ + _D("----------------> SMACK:\ + Jobs::WidgetInstall::TaskSmack::SmackPrivilegeStep()"); +#ifdef WRT_SMACK_ENABLED + /* TODO : + std::string id = DPL::ToUTF8String(m_context.widgetConfig.tzAppid); + */ + std::string id = DPL::ToUTF8String(m_context.widgetConfig.tzPkgid); + char* appId = NULL; + appId = (char*)calloc(1, id.length() + 1); + snprintf(appId, id.length() + 1, "%s", id.c_str()); + + WrtDB::ConfigParserData::PrivilegeList privileges = + m_context.widgetConfig.configInfo.privilegeList; + + char** perm_list = new char*[privileges.size() + 1]; + int index = 0; + FOREACH(it, privileges) { + _D("Permission : %ls", it->name.c_str()); + int length = DPL::ToUTF8String(it->name).length(); + char *priv = new char[length + 1]; + snprintf(priv, length + 1, "%s", + DPL::ToUTF8String(it->name).c_str()); + perm_list[index++] = priv; + } + perm_list[index] = NULL; + + if (PC_OPERATION_SUCCESS != perm_app_enable_permissions(appId, APP_TYPE_WGT, + const_cast(perm_list), true)) { + _W("failure in contructing smack rules based on perm_list"); + } + + free(appId); + index = 0; + while (NULL != perm_list[index]) { + delete [] perm_list[index++]; + } + delete [] perm_list; + + m_context.job->UpdateProgress( + InstallerContext::INSTALL_SMACK_ENABLE, + "Widget SMACK Enabled"); +#endif +} + +void TaskSmack::StepAddLabelNPRuntime() +{ + _D("----------------> SMACK:\ + Jobs::WidgetInstall::TaskSmack::StepAddLabelNPRuntime()"); + if (0 == access(m_context.locations->getNPPluginsDir().c_str(), F_OK)) { + if (PC_OPERATION_SUCCESS != + perm_app_setup_path(DPL::ToUTF8String(m_context.widgetConfig.tzPkgid).c_str(), + m_context.locations->getNPPluginsExecFile().c_str(), + PERM_APP_PATH_NPRUNTIME)) { + _E("failed to set smack execute label to %s", + m_context.locations->getNPPluginsExecFile().c_str()); + } + } +} + +void TaskSmack::StepRevokeForUpdate() +{ + _D("----------------> SMACK:\ + Jobs::WidgetInstall::TaskSmack::StepRevokePrivilegeForUpdate()"); +#ifdef WRT_SMACK_ENABLED + if (PC_OPERATION_SUCCESS != perm_app_revoke_permissions(m_pkgId)) { + _W("failure in revoking smack permissions"); + } +#endif +} + +void TaskSmack::StepAbortSmack() +{ + _D("----------------> SMACK:\ + Jobs::WidgetInstall::TaskSmack::StepAbortSmack()"); +#ifdef WRT_SMACK_ENABLED + + if (PC_OPERATION_SUCCESS != perm_app_revoke_permissions(m_pkgId)) { + _W("failure in revoking smack permissions"); + } + + if (PC_OPERATION_SUCCESS != perm_app_uninstall(m_pkgId)) { + _W("failure in removing smack rules file"); + } + free(m_pkgId); +#endif +} + +bool TaskSmack::setLabelForSharedDir(const char* pkgId) +{ + /* /shared directory */ + if (PC_OPERATION_SUCCESS != perm_app_setup_path(pkgId, + m_context.locations->getSharedRootDir().c_str(), + APP_PATH_ANY_LABEL, "_")) { + _W("Add label to %s", m_context.locations->getUserDataRootDir().c_str()); + } + + /* /shared/res directory */ + if (PC_OPERATION_SUCCESS != perm_app_setup_path(pkgId, + m_context.locations->getSharedResourceDir().c_str(), + APP_PATH_ANY_LABEL, "_")) { + _W("Add label to %s", m_context.locations->getSharedResourceDir().c_str()); + } + + /* /shared/trusted directory */ + CertificatePtr rootCert = m_context.widgetSecurity.getAuthorCertificatePtr(); + if (rootCert.Get() != NULL) { + ValidationCore::Crypto::Hash::SHA1 sha1; + sha1.Append(rootCert->getDER()); + sha1.Finish(); + std::string sha1String = sha1.ToBase64String(); + size_t iPos = sha1String.find("/"); + while(iPos < std::string::npos) { + sha1String.replace(iPos, 1, "#"); + iPos = sha1String.find("/"); + } + + _D("sha1 label string : %s", sha1String.c_str()); + + if (PC_OPERATION_SUCCESS != perm_app_setup_path(pkgId, + m_context.locations->getSharedTrustedDir().c_str(), + APP_PATH_GROUP_RW, sha1String.c_str())) { + _W("Add label to %s", m_context.locations->getBinaryDir().c_str()); + } + } + + /* /shared/data directory */ + if (PC_OPERATION_SUCCESS != perm_app_setup_path(pkgId, + m_context.locations->getSharedDataDir().c_str(), + APP_PATH_PUBLIC_RO)) { + _W("Add label to %s", m_context.locations->getSharedDataDir().c_str()); + } + + return true; +} + +void TaskSmack::StartStep() +{ + _D("--------- : START ----------"); + if (PC_OPERATION_SUCCESS != perm_begin()) { + _E("Failed to smack transaction begin."); + ThrowMsg(Exceptions::SmackTransactionFailed, "Failed to smack transaction begin"); + } +} + +void TaskSmack::EndStep() +{ + _D("--------- : END ----------"); + if (PC_OPERATION_SUCCESS != perm_end()) { + _E("Failed to smack transaction end."); + ThrowMsg(Exceptions::SmackTransactionFailed, "Failed to smack transaction end"); + } +} +} //namespace WidgetInstall +} //namespace Jobs diff --git a/src_mobile/jobs/widget_install/task_smack.h b/src_mobile/jobs/widget_install/task_smack.h new file mode 100644 index 0000000..d1895c2 --- /dev/null +++ b/src_mobile/jobs/widget_install/task_smack.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file task_smack.h + * @author Piotr Kozbial (p.kozbial@samsung.com) + * @version 1.0 + * @brief Header file for installer task smack + */ +#ifndef INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_SMACK_H +#define INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_SMACK_H + +#include + +class InstallerContext; + +namespace Jobs { +namespace WidgetInstall { +class TaskSmack : + public DPL::TaskDecl +{ + private: + InstallerContext& m_context; + char* m_pkgId; + + void StepSetInstall(); + void StepSmackFolderLabeling(); + void StepSmackPrivilege(); + void StepAddLabelNPRuntime(); + void StepRevokeForUpdate(); + void StepAbortSmack(); + + bool setLabelForSharedDir(const char* pkgId); + + void StartStep(); + void EndStep(); + + public: + TaskSmack(InstallerContext& context); +}; +} //namespace WidgetInstall +} //namespace Jobs + +#endif /* INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_SMACK_H */ diff --git a/src_mobile/jobs/widget_install/task_update_files.cpp b/src_mobile/jobs/widget_install/task_update_files.cpp new file mode 100644 index 0000000..ef27d30 --- /dev/null +++ b/src_mobile/jobs/widget_install/task_update_files.cpp @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file task_update_files.cpp + * @author Soyoung Kim (sy037.kim@samsung.com) + * @version 1.0 + * @brief Implementation file for installer task update files + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace WrtDB; + +namespace { +inline const char* GetWidgetBackupDirPath() +{ + return "backup"; +} +} + +namespace Jobs { +namespace WidgetInstall { +TaskUpdateFiles::TaskUpdateFiles(InstallerContext& context) : + DPL::TaskDecl(this), + m_context(context) +{ + AddStep(&TaskUpdateFiles::StartStep); + AddStep(&TaskUpdateFiles::StepBackupDirectory); + AddStep(&TaskUpdateFiles::EndStep); + + AddAbortStep(&TaskUpdateFiles::StepAbortBackupDirectory); +} + +void TaskUpdateFiles::StepBackupDirectory() +{ + _D("StepCreateBackupFolder"); + + Try { + std::string pkgid = + DPL::ToUTF8String(m_context.widgetConfig.tzPkgid); + if (APP2EXT_SD_CARD == app2ext_get_app_location(pkgid.c_str())) { + _D("Installed external directory"); + WidgetInstallToExtSingleton::Instance().initialize(pkgid); + WidgetInstallToExtSingleton::Instance().disable(); + } + } Catch(WidgetInstallToExt::Exception::ErrorInstallToExt) { + _E("Failed disable app2sd"); + ReThrowMsg(Exceptions::BackupFailed, "Error occurs during disable app2sd"); + } + + std::string backPath = m_context.locations->getBackupDir(); + _D("Backup resource directory path : %s", backPath.c_str()); + std::string pkgPath = m_context.locations->getPackageInstallationDir(); + + if (0 == access(backPath.c_str(), F_OK)) { + if (!WrtUtilRemove(backPath)) { + ThrowMsg(Exceptions::RemovingFolderFailure, + "Error occurs during removing backup resource directory"); + } + } + _D("copy : %s to %s", pkgPath.c_str(), backPath.c_str()); + if ((rename(pkgPath.c_str(), backPath.c_str())) != 0) { + _E("Failed to rename %s to %s", pkgPath.c_str(), backPath.c_str()); + ThrowMsg(Exceptions::BackupFailed, + "Error occurs during rename file"); + } + + WrtUtilMakeDir(pkgPath); +} + +void TaskUpdateFiles::StepAbortBackupDirectory() +{ + _D("StepAbortCopyFiles"); + + std::string backPath = m_context.locations->getBackupDir(); + std::string pkgPath = m_context.locations->getPackageInstallationDir(); + + _D("Backup Folder %s to %s", backPath.c_str(), pkgPath.c_str()); + + if (!WrtUtilRemove(pkgPath)) { + _E("Failed to remove %s", pkgPath.c_str()); + } + + if (rename(backPath.c_str(), pkgPath.c_str()) != 0) { + _E("Failed to rename %s to %s", backPath.c_str(), pkgPath.c_str()); + } +} + +void TaskUpdateFiles::StartStep() +{ + _D("--------- : START ----------"); +} + +void TaskUpdateFiles::EndStep() +{ + m_context.job->UpdateProgress( + InstallerContext::INSTALL_CREATE_BACKUP_DIR, + "Backup directory created for update"); + + _D("--------- : END ----------"); +} +} //namespace WidgetInstall +} //namespace Jobs diff --git a/src_mobile/jobs/widget_install/task_update_files.h b/src_mobile/jobs/widget_install/task_update_files.h new file mode 100644 index 0000000..1d02e0e --- /dev/null +++ b/src_mobile/jobs/widget_install/task_update_files.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file task_update_files.h + * @author Soyoung Kim (sy037.kim@samsung.com) + * @version 1.0 + * @brief Header file for installer task update files + */ +#ifndef INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_UPDATE_FILES_H +#define INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_UPDATE_FILES_H + +#include +#include +#include + +class InstallerContext; + +namespace { +typedef std::set ExistFileList; +} + +namespace Jobs { +namespace WidgetInstall { +class TaskUpdateFiles : + public DPL::TaskDecl +{ + private: + InstallerContext& m_context; + + void StepBackupDirectory(); + + void StepAbortBackupDirectory(); + + void StartStep(); + void EndStep(); + + public: + TaskUpdateFiles(InstallerContext& context); +}; +} //namespace WidgetInstall +} //namespace Jobs + +#endif /* INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_UPDATE_FILES_H */ diff --git a/src_mobile/jobs/widget_install/task_user_data_manipulation.cpp b/src_mobile/jobs/widget_install/task_user_data_manipulation.cpp new file mode 100644 index 0000000..808529e --- /dev/null +++ b/src_mobile/jobs/widget_install/task_user_data_manipulation.cpp @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file task_user_data_manipulation.cpp + * @author Soyoung Kim (sy037.kim@samsung.com) + * @version 1.0 + * @brief Implementation file for installer task user data folder + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define WEBAPP_DEFAULT_UID 5000 +#define WEBAPP_DEFAULT_GID 5000 + +namespace { +const mode_t PRIVATE_STORAGE_MODE = 0700; +const mode_t SHARED_STORAGE_MODE = 0755; +} + +using namespace WrtDB; + +namespace { +void changeOwnerForDirectory(std::string storagePath, mode_t mode) { + if (euidaccess(storagePath.c_str(), F_OK) != 0) { + if (!WrtUtilMakeDir(storagePath, mode)) { + _E("Failed to create directory : %s", storagePath.c_str()); + ThrowMsg(Jobs::WidgetInstall::Exceptions::FileOperationFailed, + "Failed to create directory : " << storagePath); + } + // '5000' is default uid, gid for applications. + // So installed applications should be launched as process of uid + // '5000'. + // the process can access private directory 'data' of itself. + if (chown(storagePath.c_str(), + WEBAPP_DEFAULT_UID, + WEBAPP_DEFAULT_GID) != 0) + { + ThrowMsg(Jobs::WidgetInstall::Exceptions::FileOperationFailed, + "Chown to invaild user"); + } + } else if (euidaccess(storagePath.c_str(), W_OK | R_OK | X_OK) == 0) { + _D("%s already exists.", storagePath.c_str()); + // Even if private directory already is created, private dircetory + // should change owner (recursively). + if (chown(storagePath.c_str(), + WEBAPP_DEFAULT_UID, + WEBAPP_DEFAULT_GID) != 0) + { + ThrowMsg(Jobs::WidgetInstall::Exceptions::FileOperationFailed, + "Chown to invaild user"); + } + if (chmod(storagePath.c_str(), mode) != 0) { + ThrowMsg(Jobs::WidgetInstall::Exceptions::FileOperationFailed, + "chmod to 0700"); + } + } else { + ThrowMsg(Jobs::WidgetInstall::Exceptions::FileOperationFailed, + "No access to private storage."); + } +} +} + +namespace Jobs { +namespace WidgetInstall { +TaskUserDataManipulation::TaskUserDataManipulation(InstallerContext& context) : + DPL::TaskDecl(this), + m_context(context) +{ + AddStep(&TaskUserDataManipulation::StartStep); + AddStep(&TaskUserDataManipulation::StepCreatePrivateStorageDir); + AddStep(&TaskUserDataManipulation::StepCreateSharedFolder); + AddStep(&TaskUserDataManipulation::StepLinkForPreload); + AddStep(&TaskUserDataManipulation::EndStep); +} + +void TaskUserDataManipulation::StepCreatePrivateStorageDir() +{ + std::string storagePath = m_context.locations->getPrivateStorageDir(); + _D("Create private storage directory : %s", m_context.locations->getPrivateStorageDir().c_str()); + + changeOwnerForDirectory(storagePath, PRIVATE_STORAGE_MODE); + + if (m_context.isUpdateMode) { //update + std::string backData = m_context.locations->getBackupPrivateDir(); + _D("copy private storage %s to %s", backData.c_str(), storagePath.c_str()); + if (!DirectoryApi::DirectoryCopy(backData, storagePath)) { + _E("Failed to rename %s to %s", backData.c_str(), storagePath.c_str()); + ThrowMsg(Exceptions::BackupFailed, + "Error occurs copy private strage files"); + } + } + + std::string tempStoragePath = m_context.locations->getPrivateTempStorageDir(); + _D("Create temp private storage directory : %s", tempStoragePath.c_str()); + changeOwnerForDirectory(tempStoragePath, PRIVATE_STORAGE_MODE); +} + +void TaskUserDataManipulation::StepLinkForPreload() +{ + if (m_context.mode.rootPath == InstallMode::RootPath::RO) { + std::string optRes = m_context.locations->getUserDataRootDir() + + WrtDB::GlobalConfig::GetWidgetResPath(); + std::string usrRes = m_context.locations->getPackageInstallationDir() + + WrtDB::GlobalConfig::GetWidgetResPath(); + + if (0 != access(optRes.c_str(), F_OK)) { + _D("Make symbolic name for preload app %s to %s", usrRes.c_str(), optRes.c_str()); + + if (symlink(usrRes.c_str(), optRes.c_str()) != 0) + { + int error = errno; + if (error) + _E("Failed to make a symbolic name for a file [%s]", (DPL::GetErrnoString(error)).c_str()); + ThrowMsg(Exceptions::FileOperationFailed, + "Symbolic link creating is not done."); + } + } + + /* link for data directory */ + std::string storagePath = m_context.locations->getPrivateStorageDir(); + std::string dataDir = m_context.locations->getPackageInstallationDir() + + "/" + WrtDB::GlobalConfig::GetWidgetPrivateStoragePath(); + if (0 != access(dataDir.c_str(), F_OK)) { + _D("Make symbolic name for preload app %s to %s", storagePath.c_str(), dataDir.c_str()); + + if (symlink(storagePath.c_str(), dataDir.c_str()) != 0) + { + int error = errno; + if (error) + _E("Failed to make a symbolic name for a file [%s]", (DPL::GetErrnoString(error)).c_str()); + ThrowMsg(Exceptions::FileOperationFailed, + "Symbolic link creating is not done."); + } + changeOwnerForDirectory(dataDir, PRIVATE_STORAGE_MODE); + } + + if (m_context.widgetConfig.packagingType != PKG_TYPE_HYBRID_WEB_APP) { + std::string widgetBinPath = m_context.locations->getBinaryDir(); + std::string userBinPath = m_context.locations->getUserBinaryDir(); + _D("Make symbolic link for preload app %s to %s", widgetBinPath.c_str(), userBinPath.c_str()); + if (symlink(widgetBinPath.c_str(), userBinPath.c_str()) != 0) + { + int error = errno; + if (error) + _E("Failed to make a symbolic name for a file [%s]", (DPL::GetErrnoString(error)).c_str()); + ThrowMsg(Exceptions::FileOperationFailed, + "Symbolic link creating is not done."); + } + + } + } +} + +void TaskUserDataManipulation::StepCreateSharedFolder() +{ + _D("StepCreateSharedFolder"); + std::string sharedPath = m_context.locations->getSharedRootDir(); + _D("Create shared directory : %s", m_context.locations->getSharedRootDir().c_str()); + + WrtUtilMakeDir(sharedPath); + WrtUtilMakeDir(m_context.locations->getSharedResourceDir()); + + changeOwnerForDirectory(m_context.locations->getSharedDataDir(), + SHARED_STORAGE_MODE); + changeOwnerForDirectory(m_context.locations->getSharedTrustedDir(), + SHARED_STORAGE_MODE); + + + // additional check for rootPath installation + // If this app is preloaded, "shared" diretory is already on place and do not needs to be moved + // TODO: why "shared" is on RW partion always but "data" and "tmp" are linked + if (m_context.isUpdateMode + && !(m_context.mode.rootPath == InstallMode::RootPath::RO + && m_context.mode.installTime == InstallMode::InstallTime::PRELOAD)) { + + /* Restore /shared/data */ + _D("copy %s to %s", m_context.locations->getBackupSharedDataDir().c_str(), m_context.locations->getSharedDataDir().c_str()); + if (!DirectoryApi::DirectoryCopy( + m_context.locations->getBackupSharedDataDir(), + m_context.locations->getSharedDataDir())) { + _E("Failed to rename %s to %s", m_context.locations->getBackupSharedDataDir().c_str(), m_context.locations->getSharedDataDir().c_str()); + ThrowMsg(Exceptions::BackupFailed, + "Error occurs copy shared strage files"); + } + + /* Restore /shared/trusted */ + _D("copy %s to %s", m_context.locations->getBackupSharedTrustedDir().c_str(), m_context.locations->getSharedTrustedDir().c_str()); + if (!DirectoryApi::DirectoryCopy( + m_context.locations->getBackupSharedTrustedDir(), + m_context.locations->getSharedTrustedDir())) { + _E("Failed to rename %s to %s", m_context.locations->getBackupSharedTrustedDir().c_str(), m_context.locations->getSharedTrustedDir().c_str()); + ThrowMsg(Exceptions::BackupFailed, + "Error occurs copy shared strage files"); + } + } +} + +void TaskUserDataManipulation::StartStep() +{ + _D("--------- : START ----------"); +} + +void TaskUserDataManipulation::EndStep() +{ + _D("--------- : END ----------"); +} +} //namespace WidgetInstall +} //namespace Jobs diff --git a/src_mobile/jobs/widget_install/task_user_data_manipulation.h b/src_mobile/jobs/widget_install/task_user_data_manipulation.h new file mode 100644 index 0000000..fbfabcc --- /dev/null +++ b/src_mobile/jobs/widget_install/task_user_data_manipulation.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file task_user_data_manipulation.cpp + * @author Soyoung Kim (sy037.kim@samsung.com) + * @version 1.0 + * @brief Implementation file for installer task user data folder + */ +#ifndef JOS_WIDGET_INSTALL_TASK_USER_DATA_MANIPULATION_H +#define JOS_WIDGET_INSTALL_TASK_USER_DATA_MANIPULATION_H + +#include + +class InstallerContext; + +namespace Jobs { +namespace WidgetInstall { +class TaskUserDataManipulation : + public DPL::TaskDecl +{ + InstallerContext& m_context; + + void StartStep(); + void EndStep(); + void StepCreatePrivateStorageDir(); + void StepCreateSharedFolder(); + void StepLinkForPreload(); + + public: + TaskUserDataManipulation(InstallerContext& context); +}; +} //namespace WidgetInstall +} //namespace Jobs + +#endif //JOS_WIDGET_INSTALL_TASK_USER_DATA_MANIPULATION_H diff --git a/src_mobile/jobs/widget_install/view_mode.h b/src_mobile/jobs/widget_install/view_mode.h new file mode 100644 index 0000000..a4acc39 --- /dev/null +++ b/src_mobile/jobs/widget_install/view_mode.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file view_mode.h + * @author Krzysztof Jackiewicz (k.jackiewicz@samsung.com) + * @version 1.0 + */ + +#ifndef SRC_JOBS_WIDGET_INSTALL_VIEW_MODE_H_ +#define SRC_JOBS_WIDGET_INSTALL_VIEW_MODE_H_ + +namespace Jobs { +namespace WidgetInstall { +enum ViewMode +{ + WINDOWED = 0, + FLOATING, + FULLSCREEN, + MAXIMIZED, + MINIMIZED +}; +} // WidgetInstall +} // Jobs + +#endif /* SRC_JOBS_WIDGET_INSTALL_VIEW_MODE_H_ */ diff --git a/src_mobile/jobs/widget_install/widget_install_context.h b/src_mobile/jobs/widget_install/widget_install_context.h new file mode 100644 index 0000000..967a737 --- /dev/null +++ b/src_mobile/jobs/widget_install/widget_install_context.h @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file installer_structs.h + * @author Pawel Sikorski (p.sikorski@samgsung.com) + * @version + * @brief Definition file of installer tasks data structures + */ +#ifndef INSTALLER_CONTEXT_H +#define INSTALLER_CONTEXT_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Jobs { +namespace WidgetInstall { +class JobWidgetInstall; +} //namespace Jobs +} //namespace WidgetInstall + +class WidgetModel; + +typedef std::map RequestedDevCapsMap; + +struct InstallerContext +{ + typedef enum InstallStepEnum + { + INSTALL_START = 0, + INSTALL_PARSE_CONFIG, + INSTALL_CHECK_FILE, + + INSTALL_RDS_DELTA_CHECK, + INSTALL_RDS_PREPARE, + + INSTALL_CREATE_BACKUP_DIR, /* For Update */ + INSTALL_DIR_CREATE, + INSTALL_UNZIP_WGT, + INSTALL_WIDGET_CONFIG1, + INSTALL_WIDGET_CONFIG2, + INSTALL_DIGSIG_CHECK, + INSTALL_CERT_CHECK, + INSTALL_CERTIFY_LEVEL_CHECK, + INSTALL_ECRYPTION_FILES, + INSTALL_BACKUP_ICONFILE, /* For Update */ + INSTALL_COPY_ICONFILE, + INSTALL_COPY_LIVEBOX_FILES, + INSTALL_CREATE_EXECFILE, + INSTALL_CREATE_MANIFEST, + INSTALL_INSTALL_OSPSVC, + INSTALL_NEW_DB_INSERT, + INSTALL_ACE_PREPARE, + INSTALL_ACE_CHECK, + INSTALL_SMACK_ENABLE, + INSTALL_PKGINFO_UPDATE, + INSTALL_SET_CERTINFO, + + INSTALL_END + } InstallStep; + + // Installation state variables + WrtDB::WidgetRegisterInfo widgetConfig; ///< WidgetConfigInfo + DPL::Optional locations; + Jobs::WidgetInstall::WidgetSecurity widgetSecurity; ///< Widget Domain + // information. + InstallStep installStep; ///< current step of installation + Jobs::WidgetInstall::JobWidgetInstall *job; + ///< Whether this is an update or normal installation + Jobs::WidgetInstall::FeatureLogicPtr featureLogic; + /** List of dev-caps that are requested in widget config file. + * Additional flag tells whether dev cap gets "static" permission + * (will always have PERMIT from ACE Policy). They will therefore receive + * static SMACK permission. (They may be forbidden because + * of ACE User Settings, but for now we do not protect this + * case with SMACK). */ + RequestedDevCapsMap staticPermittedDevCaps; + std::string installInfo; /// + InstallLocationType locationType; + bool isUpdateMode; + InstallMode mode; + DPL::String callerPkgId; + + std::string requestedPath; ///input path of widget + bool needEncryption; ///for configuring right task if encryption needed + int certLevel; +}; + +#endif // INSTALLER_CONTEXT_H diff --git a/src_mobile/jobs/widget_install/widget_install_errors.h b/src_mobile/jobs/widget_install/widget_install_errors.h new file mode 100644 index 0000000..ed0e6fb --- /dev/null +++ b/src_mobile/jobs/widget_install/widget_install_errors.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file installer_errors.h + * @author Pawel Sikorski (p.sikorski@samgsung.com) + * @version + * @brief + */ + +#ifndef INSTALLER_ERRORS_H_ +#define INSTALLER_ERRORS_H_ + +#include +#include +#include + +//TODO SafeException(...) + +using namespace Jobs::Exceptions; + +namespace Jobs { +namespace WidgetInstall { +namespace Exceptions { + +DECLARE_JOB_EXCEPTION_BASE(JobExceptionBase, Base, ErrorUnknown) + +DECLARE_JOB_EXCEPTION(Base, OpenZipFailed, ErrorPackageInvalid) +DECLARE_JOB_EXCEPTION(Base, ZipEmpty, ErrorPackageInvalid) +DECLARE_JOB_EXCEPTION(Base, ExtractFileFailed, ErrorPackageInvalid) +DECLARE_JOB_EXCEPTION(Base, EmptyPluginsDirectory, ErrorPackageInvalid) +DECLARE_JOB_EXCEPTION(Base, PluginsSubdirectory, ErrorPackageInvalid) +DECLARE_JOB_EXCEPTION(Base, RDSDeltaFailure, ErrorPackageInvalid) +DECLARE_JOB_EXCEPTION(Base, MissingConfig, ErrorPackageInvalid) +DECLARE_JOB_EXCEPTION(Base, InvalidStartFile, ErrorPackageInvalid) + +DECLARE_JOB_EXCEPTION(Base, PackageLowerVersion, ErrorPackageLowerVersion) + +DECLARE_JOB_EXCEPTION(Base, ManifestInvalid, ErrorManifestInvalid) + +DECLARE_JOB_EXCEPTION(Base, WidgetConfigFileNotFound, ErrorConfigNotFound) +DECLARE_JOB_EXCEPTION(Base, WidgetConfigFileInvalid, ErrorConfigInvalid) + +DECLARE_JOB_EXCEPTION(Base, SignatureNotFound, ErrorSignatureNotFound) + +DECLARE_JOB_EXCEPTION(Base, SignatureInvalid, ErrorSignatureInvalid) + +DECLARE_JOB_EXCEPTION(Base, SignatureVerificationFailed, ErrorSignatureVerificationFailed) + +DECLARE_JOB_EXCEPTION(Base, RootCertificateNotFound, ErrorRootCertificateNotFound) + +DECLARE_JOB_EXCEPTION(Base, CertificationInvaid, ErrorCertificationInvaid) +DECLARE_JOB_EXCEPTION(Base, NotMatchedCertification, ErrorCertificationInvaid) + +DECLARE_JOB_EXCEPTION(Base, CertificateChainVerificationFailed, ErrorCertificateChainVerificationFailed) + +DECLARE_JOB_EXCEPTION(Base, CertificateExpired, ErrorCertificateExpired) + +DECLARE_JOB_EXCEPTION(Base, NotAllowed, ErrorFatalError) +DECLARE_JOB_EXCEPTION(Base, WidgetRunningError, ErrorFatalError) +DECLARE_JOB_EXCEPTION(Base, DrmDecryptFailed, ErrorFatalError) +DECLARE_JOB_EXCEPTION(Base, DatabaseFailure, ErrorFatalError) +DECLARE_JOB_EXCEPTION(Base, RemovingFolderFailure, ErrorFatalError) +DECLARE_JOB_EXCEPTION(Base, RemovingFileFailure, ErrorFatalError) +DECLARE_JOB_EXCEPTION(Base, CreateVconfFailure, ErrorFatalError) +DECLARE_JOB_EXCEPTION(Base, CopyIconFailed, ErrorFatalError) +DECLARE_JOB_EXCEPTION(Base, FileOperationFailed, ErrorFatalError) +DECLARE_JOB_EXCEPTION(Base, InstallToExternalFailed, ErrorFatalError) +DECLARE_JOB_EXCEPTION(Base, BackupFailed, ErrorFatalError) +DECLARE_JOB_EXCEPTION(Base, InsertNewWidgetFailed, ErrorFatalError) +DECLARE_JOB_EXCEPTION(Base, RemoveBackupFailed, ErrorFatalError) +DECLARE_JOB_EXCEPTION(Base, UpdateFailed, ErrorFatalError) +DECLARE_JOB_EXCEPTION(Base, SetCertificateInfoFailed, ErrorFatalError) +DECLARE_JOB_EXCEPTION(Base, ErrorExternalInstallingFailure, ErrorFatalError) + +DECLARE_JOB_EXCEPTION(Base, PackageAlreadyInstalled, ErrorPackageAlreadyInstalled) +DECLARE_JOB_EXCEPTION(Base, AceCheckFailed, ErrorAceCheckFailed) +DECLARE_JOB_EXCEPTION(Base, EncryptionFailed, ErrorEncryptionFailed) +DECLARE_JOB_EXCEPTION(Base, InstallOspsvcFailed, ErrorInstallOspServcie) +DECLARE_JOB_EXCEPTION(Base, PrivilegeLevelViolation, ErrorPrivilegeLevelViolation) +DECLARE_JOB_EXCEPTION(Base, NotSupportRDSUpdate, ErrorNotSupportRDSUpdate) +DECLARE_JOB_EXCEPTION(Base, SmackTransactionFailed, ErrorFatalError) +DECLARE_JOB_EXCEPTION(Base, OutOfStorageFailed, ErrorOutOfStorage) +} //namespace +} //namespace +} //namespace + +#endif /* INSTALLER_ERRORS_H_ */ diff --git a/src_mobile/jobs/widget_install/widget_installer_struct.h b/src_mobile/jobs/widget_install/widget_installer_struct.h new file mode 100644 index 0000000..1fd865e --- /dev/null +++ b/src_mobile/jobs/widget_install/widget_installer_struct.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file widget_installer_struct.h + * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com) + * @author Grzegorz Krawczyk (g.krawczyk@samsung.com) + * @version 1.0 + * @brief Implementation file for widget installer struct + */ +#ifndef WRT_SRC_INSTALLER_CORE_INSTALLER_TASKS_WIDGET_INSTALLER_STRUCT_H_ +#define WRT_SRC_INSTALLER_CORE_INSTALLER_TASKS_WIDGET_INSTALLER_STRUCT_H_ + +//SYSTEM INCLUDES +#include + +//WRT INCLUDES +#include +#include +#include +#include +#include +#include +#include +#include + +//Widget Installer typedefs +typedef void (*InstallerFinishedCallback)( + void *userParam, + std::string tizenId, + Jobs::Exceptions::Type); + +typedef void (*InstallerProgressCallback)(void *userParam, + ProgressPercent percent, + const ProgressDescription &); + +namespace Jobs { +namespace WidgetInstall { +//InstallationStruct +typedef Jobs::JobCallbacksBase +WidgetInstallCallbackBase; + +//Widget Installation Struct +struct WidgetInstallationStruct : public WidgetInstallCallbackBase +{ + InstallMode m_installMode; + std::shared_ptr pkgmgrInterface; + + // It must be empty-constructible as a parameter of generic event + WidgetInstallationStruct() {}; + WidgetInstallationStruct( + InstallerFinishedCallback finished, + InstallerProgressCallback progress, + void *param, + InstallMode mode, + std::shared_ptr + _pkgmgrInterface + ) : + WidgetInstallCallbackBase(finished, progress, param), + m_installMode(mode), + pkgmgrInterface(_pkgmgrInterface) + {} +}; +} // namespace WidgetInstall +} // namespace Jobs + +#endif // WRT_SRC_INSTALLER_CORE_INSTALLER_TASKS_WIDGET_INSTALLER_STRUCT_H_ diff --git a/src_mobile/jobs/widget_install/widget_security.cpp b/src_mobile/jobs/widget_install/widget_security.cpp new file mode 100644 index 0000000..01644ab --- /dev/null +++ b/src_mobile/jobs/widget_install/widget_security.cpp @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file widget_security.cpp + * @author Krzysztof Jackiewicz(k.jackiewicz@samsung.com) + * @version 1.0 + * @brief + */ + +#include "widget_security.h" +#include + +namespace Jobs { +namespace WidgetInstall { +void WidgetSecurity::getCertificateChainList( + WrtDB::CertificateChainList& list, + WrtDB::CertificateSource source) const +{ + if (source == WrtDB::CertificateSource::SIGNATURE_DISTRIBUTOR) { + FOREACH(certIter, mCertificateChainList) + list.push_back(certIter->toBase64String()); + } else { + FOREACH(certIter, mAuthorsCertificateChainList) + list.push_back(certIter->toBase64String()); + } +} +} // namespace WidgetInstall +} // namespace Jobs diff --git a/src_mobile/jobs/widget_install/widget_security.h b/src_mobile/jobs/widget_install/widget_security.h new file mode 100644 index 0000000..0bc04ef --- /dev/null +++ b/src_mobile/jobs/widget_install/widget_security.h @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file widget_security.h + * @author Krzysztof Jackiewicz(k.jackiewicz@samsung.com) + * @version 1.0 + * @brief + */ + +#ifndef WACSECURITY_H_ +#define WACSECURITY_H_ + +#include +#include +#include + +namespace Jobs { +namespace WidgetInstall { +class WidgetSecurity : public WrtDB::IWidgetSecurity +{ + public: + WidgetSecurity() : + mRecognized(false), + mDistributorSigned(false) + {} + + // from IWidgetSecurity + virtual const WrtDB::WidgetCertificateDataList& getCertificateList() const + { + return mCertificateList; + } + + virtual bool isRecognized() const + { + return mRecognized; + } + + virtual bool isDistributorSigned() const + { + return mDistributorSigned; + } + + virtual void getCertificateChainList( + WrtDB::CertificateChainList& list, + WrtDB::CertificateSource source) const; + + void setRecognized(bool recognized) + { + mRecognized = recognized; + } + void setDistributorSigned(bool distributorSigned) + { + mDistributorSigned = distributorSigned; + } + void setAuthorCertificatePtr(ValidationCore::CertificatePtr certPtr) + { + mAuthorCertificate = certPtr; + } + + ValidationCore::CertificatePtr getAuthorCertificatePtr() const + { + return mAuthorCertificate; + } + ValidationCore::CertificateCollectionList& getCertificateChainListRef() + { + return mCertificateChainList; + } + + ValidationCore::CertificateCollectionList& + getAuthorsCertificateChainListRef() + { + return mAuthorsCertificateChainList; + } + + WrtDB::WidgetCertificateDataList& getCertificateListRef() + { + return mCertificateList; + } + + private: + // This data are used to evaluate policy + WrtDB::WidgetCertificateDataList mCertificateList; + + // author signature verified + bool mRecognized; + // known distribuor + bool mDistributorSigned; + // Author end entity certificate. + // Information from this certificate are shown to user + // during installation process. + ValidationCore::CertificatePtr mAuthorCertificate; + // This certificates are used by OCSP/CRL + ValidationCore::CertificateCollectionList mCertificateChainList; + // This authors certificates are used by tizen + ValidationCore::CertificateCollectionList mAuthorsCertificateChainList; +}; +} // namespace WidgetInstall +} // namespace Jobs + +#endif /* WACSECURITY_H_ */ diff --git a/src_mobile/jobs/widget_install/widget_unzip.cpp b/src_mobile/jobs/widget_install/widget_unzip.cpp new file mode 100644 index 0000000..057b6c3 --- /dev/null +++ b/src_mobile/jobs/widget_install/widget_unzip.cpp @@ -0,0 +1,375 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file widget_unzip.cpp + * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com) + * @version 1.0 + * @brief Implementation file for installer widget unzip + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace WrtDB; + +namespace { +const char *const DRM_LIB_PATH = "/usr/lib/libdrm-service-core-tizen.so"; +const size_t SPACE_SIZE = 1024 * 1024; +const char *const WEB_APP_CONFIG_XML= "config.xml"; +const char *const HYBRID_CONFIG_XML = "res/wgt/config.xml"; + +struct PathAndFilePair +{ + std::string path; + std::string file; + + PathAndFilePair(const std::string &p, + const std::string &f) : + path(p), + file(f) + {} +}; + +PathAndFilePair SplitFileAndPath(const std::string &filePath) +{ + std::string::size_type position = filePath.rfind('/'); + + // Is this only a file without a path ? + if (position == std::string::npos) { + return PathAndFilePair(std::string(), filePath); + } + + // This is full file-path pair + return PathAndFilePair(filePath.substr(0, + position), + filePath.substr(position + 1)); +} +} + +namespace Jobs { +namespace WidgetInstall { + +WidgetUnzip::WidgetUnzip(const std::string &source) +{ + Try { + m_requestFile = getDecryptedPackage(source); + m_zip.reset(new DPL::ZipInput(m_requestFile)); + } + Catch(DPL::ZipInput::Exception::OpenFailed) + { + ReThrowMsg(Exceptions::OpenZipFailed, source); + } + Catch(Exceptions::DrmDecryptFailed) + { + ReThrowMsg(Exceptions::ExtractFileFailed, source); + } +} + +void WidgetUnzip::ExtractFile(DPL::ZipInput::File *input, + const std::string &destFileName) +{ + Try + { + DPL::AbstractWaitableInputAdapter inputAdapter(input); + DPL::FileOutput output(destFileName); + + DPL::Copy(&inputAdapter, &output); + } + Catch(DPL::FileOutput::Exception::OpenFailed) + { + ReThrowMsg(Exceptions::ExtractFileFailed, destFileName); + } + Catch(DPL::CopyFailed) + { + ReThrowMsg(Exceptions::ExtractFileFailed, destFileName); + } +} + +void WidgetUnzip::unzipProgress(const std::string &destination) +{ + // Show file info + _D("Unzipping: '%s', Comment: '%s', Compressed size: %lld, Uncompressed size: %lld", + m_zipIterator->name.c_str(), m_zipIterator->comment.c_str(), m_zipIterator->compressedSize, m_zipIterator->uncompressedSize); + + // Normalize file paths + // FIXME: Implement checking for invalid characters + + // Extract file or path + std::string fileName = m_zipIterator->name; + + if (fileName[fileName.size() - 1] == '/') { + // This is path + std::string newPath = destination + "/" + + fileName.substr(0, fileName.size() - 1); + _D("Path to extract: %s", newPath.c_str()); + + // Create path in case of it is empty + createTempPath(newPath); + } else { + // This is regular file + std::string fileExtractPath = destination + "/" + fileName; + + _D("File to extract: %s", fileExtractPath.c_str()); + + // Split into pat & file pair + PathAndFilePair pathAndFile = SplitFileAndPath(fileExtractPath); + + _D("Path and file: %s : %s", pathAndFile.path.c_str(), pathAndFile.file.c_str()); + + // First, ensure that path exists + createTempPath(pathAndFile.path); + + Try + { + // Open file + std::unique_ptr file( + m_zip->OpenFile(fileName)); + + // Extract single file + ExtractFile(file.get(), fileExtractPath); + } + Catch(DPL::ZipInput::Exception::OpenFileFailed) + { + ThrowMsg(Exceptions::ExtractFileFailed, fileName); + } + } + + // Check whether there are more files to extract + if (++m_zipIterator == m_zip->end()) { + _D("Unzip progress finished successfuly"); + } else { + unzipProgress(destination); + } +} + +bool WidgetUnzip::isDRMPackage(const std::string &source) +{ + _D("Enter : isDRMPackage()"); + int ret = 0; + void* pHandle = NULL; + char* pErrorMsg = NULL; + int (*drm_oem_sapps_is_drm_file)(const char* pDcfPath, int dcfPathLen); + + pHandle = dlopen(DRM_LIB_PATH, RTLD_LAZY | RTLD_GLOBAL); + if (!pHandle) { + _E("dlopen failed : %s [%s]", source.c_str(), dlerror()); + return false; + } + + // clear existing error + dlerror(); + + drm_oem_sapps_is_drm_file = reinterpret_cast + (dlsym(pHandle, "drm_oem_sapps_is_drm_file")); + + if ((pErrorMsg = dlerror()) != NULL) { + _E("dlsym failed : %s [%s]", source.c_str(), pErrorMsg); + dlclose(pHandle); + return false; + } + + if (drm_oem_sapps_is_drm_file == NULL) { + _E("drm_oem_sapps_is_drm_file is NULL : %s", source.c_str()); + dlclose(pHandle); + return false; + } + + ret = drm_oem_sapps_is_drm_file(source.c_str(), source.length()); + dlclose(pHandle); + if (1 == ret) { + _D("%s is DRM file", source.c_str()); + return true; + } + _D("%s isn't DRM file", source.c_str()); + return false; +} + +bool WidgetUnzip::decryptDRMPackage(const std::string &source, const std::string + &decryptedSource) +{ + _D("Enter : decryptDRMPackage()"); + int ret = 0; + void* pHandle = NULL; + char* pErrorMsg = NULL; + int (*drm_oem_sapps_decrypt_package)(const char* pDcfPath, int dcfPathLen, + const char* pDecryptedFile, int decryptedFileLen); + + pHandle = dlopen(DRM_LIB_PATH, RTLD_LAZY | RTLD_GLOBAL); + if (!pHandle) { + _E("dlopen failed : %s [%s]", source.c_str(), dlerror()); + return false; + } + + // clear existing error + dlerror(); + + drm_oem_sapps_decrypt_package = reinterpret_cast + (dlsym(pHandle, "drm_oem_sapps_decrypt_package")); + + if ((pErrorMsg = dlerror()) != NULL) { + _E("dlsym failed : %s [%s]", source.c_str(), pErrorMsg); + dlclose(pHandle); + return false; + } + + if (drm_oem_sapps_decrypt_package == NULL) { + _E("drm_oem_sapps_decrypt_package is NULL : %s", source.c_str()); + dlclose(pHandle); + return false; + } + + ret = drm_oem_sapps_decrypt_package(source.c_str(), source.length(), + decryptedSource.c_str(), decryptedSource.length()); + dlclose(pHandle); + if (1 == ret) { + _D("%s is decrypted : %s", source.c_str(), decryptedSource.c_str()); + return true; + } + return false; +} + +std::string WidgetUnzip::getDecryptedPackage(const std::string &source) +{ + _D("Check DRM..."); + if (isDRMPackage(source)) { + std::string decryptedFile; + size_t found = source.find_last_of(".wgt"); + if (found == std::string::npos) { + decryptedFile += source + "_tmp.wgt"; + } else { + decryptedFile += source.substr(0, source.find_last_not_of(".wgt") + + 1) + "_tmp.wgt"; + } + + _D("decrypted file name : %s", decryptedFile.c_str()); + if (!decryptDRMPackage(source, decryptedFile)) { + _E("Failed decrypt drm file"); + ThrowMsg(Exceptions::DrmDecryptFailed, source); + } + return decryptedFile; + } + return source; +} + +void WidgetUnzip::unzipWgtFile(const std::string &destination) +{ + _D("Prepare to unzip..."); + Try + { + _D("wgtFile : %s", m_requestFile.c_str()); + _D("Widget package comment: %s", m_zip->GetGlobalComment().c_str()); + + // Widget package must not be empty + if (m_zip->empty()) { + ThrowMsg(Exceptions::ZipEmpty, m_requestFile); + } + + // Set iterator to first file + m_zipIterator = m_zip->begin(); + + unzipProgress(destination); + + // Unzip finished, close internal structures + m_zip.reset(); + + // Done + _D("Unzip finished"); + } + Catch(DPL::ZipInput::Exception::OpenFailed) + { + ReThrowMsg(Exceptions::OpenZipFailed, m_requestFile); + } + Catch(DPL::ZipInput::Exception::SeekFileFailed) + { + ThrowMsg(Exceptions::ExtractFileFailed, m_requestFile); + } + Catch(Exceptions::DrmDecryptFailed) + { + ReThrowMsg(Exceptions::ExtractFileFailed, m_requestFile); + } +} + +bool WidgetUnzip::checkAvailableSpace(const std::string &destination) +{ + _D("checkAvailableSpace ... "); + + double unCompressedSize = m_zip->GetTotalUncompressedSize(); + _D("unCompressedSize : %ld", unCompressedSize); + + struct statvfs vfs; + if (-1 == statvfs(destination.c_str(), &vfs)) { + _E("There is no space for installation"); + return false; + } + + double freeSize = (double)vfs.f_bsize * vfs.f_bavail; + _D("Space Size : %ld", freeSize); + + if (unCompressedSize + SPACE_SIZE >= freeSize) { + _E("There is no space for installation"); + return false; + } + return true; +} + +void WidgetUnzip::unzipConfiguration(const std::string &destination, + WrtDB::PackagingType* type) +{ + _D("unzipConfiguration"); + + Try { + _D("wgtFile : %s", m_requestFile.c_str()); + + std::unique_ptr configFile; + + Try { + configFile.reset(m_zip->OpenFile(HYBRID_CONFIG_XML)); + *type = PKG_TYPE_HYBRID_WEB_APP; + } Catch(DPL::ZipInput::Exception::OpenFileFailed) { + configFile.reset(m_zip->OpenFile(WEB_APP_CONFIG_XML)); + *type = PKG_TYPE_NOMAL_WEB_APP; + } + + std::string extractPath = destination + "/" + WEB_APP_CONFIG_XML; + ExtractFile(configFile.get(), extractPath); + } + Catch(DPL::ZipInput::Exception::OpenFailed) + { + ReThrowMsg(Exceptions::OpenZipFailed, m_requestFile); + } + Catch(DPL::ZipInput::Exception::OpenFileFailed) + { + ThrowMsg(Exceptions::ExtractFileFailed, "config.xml"); + } + Catch(Exceptions::DrmDecryptFailed) + { + ReThrowMsg(Exceptions::ExtractFileFailed, m_requestFile); + } +} + +} //namespace WidgetInstall +} //namespace Jobs diff --git a/src_mobile/jobs/widget_install/widget_unzip.h b/src_mobile/jobs/widget_install/widget_unzip.h new file mode 100644 index 0000000..204cde7 --- /dev/null +++ b/src_mobile/jobs/widget_install/widget_unzip.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file widget_unzip.cpp + * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com) + * @version 1.0 + * @brief Implementation file for installer task unzip + */ +#ifndef WIDGET_UNZIP_H +#define WIDGET_UNZIP_H + +#include + +#include +#include + +namespace Jobs { +namespace WidgetInstall { +class WidgetUnzip +{ + public: + WidgetUnzip(const std::string &source); + void unzipWgtFile(const std::string &destination); + void unzipConfiguration(const std::string &destination, WrtDB::PackagingType *type); + bool checkAvailableSpace(const std::string &destination); + + private: + // Unzip state + std::unique_ptr m_zip; + DPL::ZipInput::const_iterator m_zipIterator; + std::string m_requestFile; + + void unzipProgress(const std::string &destination); + void ExtractFile(DPL::ZipInput::File *input, const std::string + &destFileName); + bool isDRMPackage(const std::string &source); + bool decryptDRMPackage(const std::string &source, const std::string + &decryptedSource); + std::string getDecryptedPackage(const std::string &source); +}; + +} //namespace WidgetInstall +} //namespace Jobs + +#endif // WIDGET_UNZIP_H diff --git a/src_mobile/jobs/widget_install/widget_update_info.cpp b/src_mobile/jobs/widget_install/widget_update_info.cpp new file mode 100644 index 0000000..621907b --- /dev/null +++ b/src_mobile/jobs/widget_install/widget_update_info.cpp @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file widget_update_info.cpp + * @author Chung Jihoon (jihoon.chung@samsung.com) + * @version 1.0 + * @brief Implementation file for WidgetUpdateInfo + */ + +#include "widget_update_info.h" + +WidgetUpdateInfo::WidgetUpdateInfo( + const WrtDB::TizenAppId & appId, + const DPL::Optional &existingversion, + const DPL::Optional &incomingversion) : + tzAppId(appId), + existingVersion(existingversion), + incomingVersion(incomingversion) +{ +} + diff --git a/src_mobile/jobs/widget_install/widget_update_info.h b/src_mobile/jobs/widget_install/widget_update_info.h new file mode 100644 index 0000000..21004bd --- /dev/null +++ b/src_mobile/jobs/widget_install/widget_update_info.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file widget_update_info.h + * @author Chung Jihoon (jihoon.chung@samsung.com) + * @version 1.0 + * @brief Header file for WidgetUpdateInfo + */ +#ifndef SRC_DOMAIN_WIDGET_UPDATE_INFO_H +#define SRC_DOMAIN_WIDGET_UPDATE_INFO_H + +#include +#include + +/** + * WidgetUpdateInfo + * A structure to hold widget's information needed to be registered. + * @see WidgetConfigurationInfo + */ +struct WidgetUpdateInfo +{ + WrtDB::TizenAppId tzAppId; + // Existing widget + DPL::Optional existingVersion; + // Incoming widget + DPL::Optional incomingVersion; + + WidgetUpdateInfo() {}; + WidgetUpdateInfo(const WrtDB::TizenAppId & tzAppid, + const DPL::Optional &existringversion, + const DPL::Optional &incomingVersion); +}; + +#endif // SRC_DOMAIN_WIDGET_UPDATE_INFO_H diff --git a/src_mobile/jobs/widget_uninstall/job_widget_uninstall.cpp b/src_mobile/jobs/widget_uninstall/job_widget_uninstall.cpp new file mode 100644 index 0000000..71de26f --- /dev/null +++ b/src_mobile/jobs/widget_uninstall/job_widget_uninstall.cpp @@ -0,0 +1,277 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace WrtDB; + +namespace { //anonymous +const char* REG_TIZEN_PKGID_PATTERN = "^[a-zA-Z0-9]{10}$"; +const int PKGID_LENTH = 10; +const DPL::Utils::Path PRELOAD_INSTALLED_PATH("/usr/apps"); + +bool checkDirectoryExist(const std::string& pkgId) +{ + DPL::Utils::Path installPath(GlobalConfig::GetUserInstalledWidgetPath()); + installPath /= pkgId; + return installPath.Exists(); +} +} + +namespace Jobs { +namespace WidgetUninstall { + +class UninstallerTaskFail : + public DPL::TaskDecl +{ + private: + WidgetStatus m_status; + + void StepFail() + { + if (WidgetStatus::NOT_INSTALLED == m_status) { + ThrowMsg(Jobs::WidgetUninstall::Exceptions::WidgetNotExist, + "Widget does not exist"); + } else if (WidgetStatus::PREALOAD == m_status) { + ThrowMsg(Jobs::WidgetUninstall::Exceptions::Unremovable, + "Widget cann't uninstall"); + } else { + Throw(Jobs::WidgetUninstall::Exceptions::Base); + } + } + + public: + UninstallerTaskFail(WidgetStatus status) : + DPL::TaskDecl(this), + m_status(status) + + { + AddStep(&UninstallerTaskFail::StepFail); + } +}; + +JobWidgetUninstall::JobWidgetUninstall( + const std::string & tizenAppId, + const WidgetUninstallationStruct & + uninstallerStruct) : + Job(Uninstallation), + JobContextBase(uninstallerStruct), + m_exceptionCaught(Jobs::Exceptions::Success) +{ + using namespace PackageManager; + m_context.removeStarted = false; + m_context.removeFinished = false; + m_context.removeAbnormal = false; + m_context.uninstallStep = UninstallerContext::UNINSTALL_START; + m_context.job = this; + + Try + { + WidgetStatus status = getWidgetStatus(tizenAppId); + + if (WidgetStatus::Ok == status) { + WrtDB::WidgetDAOReadOnly dao(DPL::FromUTF8String(m_context.tzAppid)); + m_context.tzPkgid = DPL::ToUTF8String(dao.getTizenPkgId()); + m_context.locations = WidgetLocation(m_context.tzPkgid); + m_context.locations->registerAppid(m_context.tzAppid); + m_context.installedPath = + DPL::Utils::Path(*dao.getWidgetInstalledPath()); + m_context.manifestFile = getManifestFile(); + + _D("Widget model exists. App id : %s", m_context.tzAppid.c_str()); + + // send start signal of pkgmgr + if (GetInstallerStruct().pkgmgrInterface->setPkgname(m_context.tzPkgid)) + { + GetInstallerStruct().pkgmgrInterface->startJob(InstallationType::Uninstallation); + } + + AddTask(new TaskCheck(m_context)); + if (dao.getPackagingType() == PKG_TYPE_HYBRID_WEB_APP) { + AddTask(new TaskUninstallOspsvc(m_context)); + } + AddTask(new TaskDeletePkgInfo(m_context)); + AddTask(new TaskDbUpdate(m_context)); + AddTask(new TaskSmack(m_context)); + + AddTask(new TaskRemoveCustomHandlers(m_context)); + AddTask(new TaskRemoveFiles(m_context)); + } else if (WidgetStatus::NOT_INSTALLED == status || + WidgetStatus::PREALOAD == status) { + AddTask(new UninstallerTaskFail(status)); + } else if (WidgetStatus::ABNORMAL == status) { + m_context.locations = WidgetLocation(m_context.tzPkgid); + m_context.removeAbnormal = true; + AddTask(new TaskRemoveFiles(m_context)); + } else { + AddTask(new UninstallerTaskFail(WidgetStatus::UNRECOGNIZED)); + } + } Catch(WidgetDAOReadOnly::Exception::Base) { + AddTask(new UninstallerTaskFail(WidgetStatus::UNRECOGNIZED)); + } +} + +WidgetStatus JobWidgetUninstall::getWidgetStatus(const std::string &id) +{ + regex_t regx; + if(regcomp(®x, REG_TIZEN_PKGID_PATTERN, REG_NOSUB | REG_EXTENDED)!=0){ + _D("Regcomp failed"); + } + std::string pkgId; + DPL::Utils::Path installPath; + + Try { + if ((regexec(®x, id.c_str(), + static_cast(0), NULL, 0) == REG_NOERROR)) { + pkgId = id; + + TizenAppId appid = + WrtDB::WidgetDAOReadOnly::getTzAppId( + DPL::FromUTF8String(id)); + _D("Get appid from pkgid : %ls", appid.c_str()); + m_context.tzAppid = DPL::ToUTF8String(appid); + WrtDB::WidgetDAOReadOnly dao(appid); + installPath = DPL::Utils::Path(*dao.getWidgetInstalledPath()); + } else { + pkgId = id.substr(0, PKGID_LENTH); + WrtDB::WidgetDAOReadOnly dao(DPL::FromUTF8String(id)); + m_context.tzAppid = id; + installPath = DPL::Utils::Path(*dao.getWidgetInstalledPath()); + } + if(installPath.isSubPath(PRELOAD_INSTALLED_PATH)){ + _D("This widget is preloaded."); + } + } Catch(WidgetDAOReadOnly::Exception::WidgetNotExist) { + _D("package id : %s", pkgId.c_str()); + m_context.tzPkgid = pkgId; + if (!pkgId.empty()) { + if(checkDirectoryExist(pkgId)) { + _E("installed widget status is abnormal"); + return WidgetStatus::ABNORMAL; + } + } + return WidgetStatus::NOT_INSTALLED; + } + return WidgetStatus::Ok; +} + +std::string JobWidgetUninstall::getRemovedTizenId() const +{ + return m_context.tzAppid; +} + +bool JobWidgetUninstall::getRemoveStartedFlag() const +{ + return m_context.removeStarted; +} + +bool JobWidgetUninstall::getRemoveFinishedFlag() const +{ + return m_context.removeFinished; +} + +DPL::Utils::Path JobWidgetUninstall::getManifestFile() const +{ + std::ostringstream manifest_name; + manifest_name << m_context.tzPkgid << ".xml"; + DPL::Utils::Path manifestFile; + + const DPL::Utils::Path PRELOAD_INSTALLED_PATH("/usr/apps/" + m_context.tzPkgid); + const DPL::Utils::Path USR_PACKAGES_PATH("/usr/share/packages"); + const DPL::Utils::Path OPT_PACKAGES_PATH("/opt/share/packages"); + + if (PRELOAD_INSTALLED_PATH == m_context.installedPath) { + _D("This widget is preloaded."); + manifestFile = USR_PACKAGES_PATH; + } else { + manifestFile = OPT_PACKAGES_PATH; + } + + manifestFile /= manifest_name.str(); + _D("Manifest file : %s", manifestFile.Fullpath().c_str()); + + return manifestFile; +} + +void JobWidgetUninstall::SendProgress() +{ + using namespace PackageManager; + if (!getRemoveStartedFlag() || + (getRemoveStartedFlag() && getRemoveFinishedFlag())) + { + if (NULL != GetInstallerStruct().progressCallback) { + // send progress signal of pkgmgr + std::ostringstream percent; + percent << static_cast(GetProgressPercent()); + + _D("Call widget uninstall progressCallback"); + GetInstallerStruct().progressCallback( + GetInstallerStruct().userParam, + GetProgressPercent(), GetProgressDescription()); + } + } +} + +void JobWidgetUninstall::SendFinishedSuccess() +{ + using namespace PackageManager; + // send signal of pkgmgr + GetInstallerStruct().pkgmgrInterface->endJob(m_exceptionCaught); + + _D("Call widget uninstall success finishedCallback"); + GetInstallerStruct().finishedCallback(GetInstallerStruct().userParam, + getRemovedTizenId(), + Jobs::Exceptions::Success); +} + +void JobWidgetUninstall::SendFinishedFailure() +{ + using namespace PackageManager; + _E("Error in uninstallation step: %d", m_exceptionCaught); + _E("Message: %s", m_exceptionMessage.c_str()); + + // send signal of pkgmgr + GetInstallerStruct().pkgmgrInterface->endJob(m_exceptionCaught); + + _D("Call widget uninstall failure finishedCallback"); + GetInstallerStruct().finishedCallback(GetInstallerStruct().userParam, + getRemovedTizenId(), + m_exceptionCaught); + _D("[JobWidgetUninstall] Asynchronous failure callback status sent"); +} + +void JobWidgetUninstall::SaveExceptionData(const Jobs::JobExceptionBase &e) +{ + m_exceptionCaught = static_cast(e.getParam()); + m_exceptionMessage = e.GetMessage(); +} +} //namespace WidgetUninstall +} //namespace Jobs diff --git a/src_mobile/jobs/widget_uninstall/job_widget_uninstall.h b/src_mobile/jobs/widget_uninstall/job_widget_uninstall.h new file mode 100644 index 0000000..21bb764 --- /dev/null +++ b/src_mobile/jobs/widget_uninstall/job_widget_uninstall.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file job_widet_uninstall.h + * @brief Uninstaller header file. + * @author Radoslaw Wicik r.wicik@samsung.com + */ + +#ifndef WRT_SRC_INSTALLER_CORE_JOB_WIDGET_UNINSTALL_JOB_WIDGET_UNINSTALL_H_ +#define WRT_SRC_INSTALLER_CORE_JOB_WIDGET_UNINSTALL_JOB_WIDGET_UNINSTALL_H_ + +#include +#include +#include +#include +#include + +namespace Jobs { +namespace WidgetUninstall { + +enum class WidgetStatus +{ + Ok, NOT_INSTALLED, PREALOAD, ABNORMAL, UNRECOGNIZED +}; + +typedef JobContextBase WidgetUnistallStructBase; +typedef JobProgressBase UninstallContextBase; + +class JobWidgetUninstall : + public Job, + public UninstallContextBase, + public WidgetUnistallStructBase +{ + private: + UninstallerContext m_context; + + //TODO move it to base class of all jobs + Jobs::Exceptions::Type m_exceptionCaught; + std::string m_exceptionMessage; + + public: + /** + * @brief Uninstaller must to know which widget to uninstall. + * + * @param[in] WrtDB::TizenAppId tzAppId - widget to uninstall + */ + JobWidgetUninstall(const std::string &tizenAppId, + const WidgetUninstallationStruct& uninstallerStruct); + + std::string getRemovedTizenId() const; + bool getRemoveStartedFlag() const; + bool getRemoveFinishedFlag() const; + DPL::Utils::Path getManifestFile() const; + + WidgetStatus getWidgetStatus(const std::string &appId); + + void SendProgress(); + void SendFinishedSuccess(); + void SendFinishedFailure(); + void SaveExceptionData(const Jobs::JobExceptionBase &e); +}; +} //namespace WidgetUninstall +} //namespace Jobs + +#endif // WRT_SRC_INSTALLER_CORE_JOB_WIDGET_UNINSTALL_JOB_WIDGET_UNINSTALL_H_ diff --git a/src_mobile/jobs/widget_uninstall/task_check.cpp b/src_mobile/jobs/widget_uninstall/task_check.cpp new file mode 100644 index 0000000..22a7e91 --- /dev/null +++ b/src_mobile/jobs/widget_uninstall/task_check.cpp @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file task_check.cpp + * @author Pawel Sikorski(p.sikorski@samsung.com) + * @version 1.0 + * @brief Header file for widget uninstall task check + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Jobs { +namespace WidgetUninstall { +TaskCheck::TaskCheck(UninstallerContext& context) : + DPL::TaskDecl(this), + m_context(context) +{ + AddStep(&TaskCheck::StartStep); + AddStep(&TaskCheck::StepUninstallPreCheck); + AddStep(&TaskCheck::StepCheckMDM); + AddStep(&TaskCheck::EndStep); +} + +TaskCheck::~TaskCheck() +{} + +void TaskCheck::StartStep() +{ + _D("--------- : START ----------"); +} + +void TaskCheck::EndStep() +{ + m_context.job->UpdateProgress(UninstallerContext::UNINSTALL_PRECHECK, + "Uninstall pre-checking Finished"); + _D("--------- : END ----------"); +} + +void TaskCheck::StepUninstallPreCheck() +{ + bool isRunning = false; + int ret = app_manager_is_running(m_context.tzAppid.c_str(), &isRunning); + if (APP_MANAGER_ERROR_NONE != ret) { + _E("Fail to get running state"); + ThrowMsg(Exceptions::PlatformAPIFailure, + "Fail to get widget state"); + } + + if (true == isRunning) { + // get app_context for running application + // app_context must be released with app_context_destroy + app_context_h appCtx = NULL; + ret = app_manager_get_app_context(m_context.tzAppid.c_str(), &appCtx); + if (APP_MANAGER_ERROR_NONE != ret) { + _E("Fail to get app_context"); + ThrowMsg(Exceptions::AppIsRunning, + "Widget is not stopped. Cannot uninstall!"); + } + + // terminate app_context_h + ret = app_manager_terminate_app(appCtx); + if (APP_MANAGER_ERROR_NONE != ret) { + _E("Fail to terminate running application"); + app_context_destroy(appCtx); + ThrowMsg(Exceptions::AppIsRunning, + "Widget is not stopped. Cannot uninstall!"); + } else { + app_context_destroy(appCtx); + // app_manager_terminate_app isn't sync API + // wait until application isn't running (50ms * 100) + bool isStillRunning = true; + int checkingloop = 100; + struct timespec duration = { 0, 50 * 1000 * 1000 }; + while (--checkingloop >= 0) { + nanosleep(&duration, NULL); + int ret = app_manager_is_running(m_context.tzAppid.c_str(), &isStillRunning); + if (APP_MANAGER_ERROR_NONE != ret) { + _E("Fail to get running state"); + ThrowMsg(Exceptions::PlatformAPIFailure, + "Fail to get widget state"); + } + if (!isStillRunning) { + break; + } + } + if (isStillRunning) { + _E("Fail to terminate running application"); + ThrowMsg(Exceptions::AppIsRunning, + "Widget is not stopped. Cannot uninstall!"); + } + _D("terminate application"); + } + } + + _D("Widget Can be uninstalled, Pkgname : %s", m_context.tzAppid.c_str()); +} + +void TaskCheck::StepCheckMDM() +{ + _D("StepCheckMDM"); + + if (PMINFO_R_OK != pkgmgr_parser_check_mdm_policy_for_uninstallation( + m_context.manifestFile.Fullpath().c_str())) { + _E("Failed to check mdm policy"); + ThrowMsg(Exceptions::CheckMDMPolicyFailure, "Can't uninstall! Because of MDM policy"); + } +} +} //namespace WidgetUninstall +} //namespace Jobs diff --git a/src_mobile/jobs/widget_uninstall/task_check.h b/src_mobile/jobs/widget_uninstall/task_check.h new file mode 100644 index 0000000..29c00db --- /dev/null +++ b/src_mobile/jobs/widget_uninstall/task_check.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file task_check.h + * @author Pawel Sikorski(p.sikorski@samsung.com) + * @version 1.0 + * @brief Header file for widget uninstall task check + */ + +#ifndef WRT_SRC_INSTALLER_CORE_JOB_WIDGET_UNINSTALL_TASK_CHECK_H_ +#define WRT_SRC_INSTALLER_CORE_JOB_WIDGET_UNINSTALL_TASK_CHECK_H_ + +#include + +struct UninstallerContext; //forward declaration +class WidgetModel; + +namespace Jobs { +namespace WidgetUninstall { +class TaskCheck : + public DPL::TaskDecl +{ + private: + //context + UninstallerContext& m_context; + + //steps + void StepUninstallPreCheck(); + void StepCheckMDM(); + void StartStep(); + void EndStep(); + + public: + TaskCheck(UninstallerContext& context); + virtual ~TaskCheck(); +}; +} //namespace WidgetUninstall +} //namespace Jobs + +#endif /* WRT_SRC_INSTALLER_CORE_JOB_WIDGET_UNINSTALL_TASK_CHECK_H_ */ diff --git a/src_mobile/jobs/widget_uninstall/task_db_update.cpp b/src_mobile/jobs/widget_uninstall/task_db_update.cpp new file mode 100644 index 0000000..f38280d --- /dev/null +++ b/src_mobile/jobs/widget_uninstall/task_db_update.cpp @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file task_db_update.cpp + * @author Lukasz Wrzosek(l.wrzosek@samsung.com) + * @version 1.0 + * @brief Implementation file for uninstaller task database updating + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace WrtDB; + +namespace Jobs { +namespace WidgetUninstall { +TaskDbUpdate::TaskDbUpdate(UninstallerContext& context) : + DPL::TaskDecl(this), + m_context(context) +{ + AddStep(&TaskDbUpdate::StartStep); + AddStep(&TaskDbUpdate::StepRemoveExternalLocations); + AddStep(&TaskDbUpdate::StepDbUpdate); + AddStep(&TaskDbUpdate::StepLiveboxDBDelete); + AddStep(&TaskDbUpdate::EndStep); +} + +TaskDbUpdate::~TaskDbUpdate() +{} + +void TaskDbUpdate::StepDbUpdate() +{ + Try + { + //TODO: widget handle should not be used any more + ace_unregister_widget(static_cast( + WidgetDAOReadOnly::getHandle(DPL:: + FromUTF8String( + m_context. + tzAppid)))); + WidgetDAO::unregisterWidget(DPL::FromUTF8String(m_context.tzAppid)); + + _D("Unregistered widget successfully!"); + } + Catch(DPL::DB::SqlConnection::Exception::Base) + { + _E("Failed to handle StepDbUpdate!"); + ReThrowMsg(Exceptions::DatabaseFailure, + "Failed to handle StepDbUpdate!"); + } +} + +void TaskDbUpdate::StepLiveboxDBDelete() +{ + int ret = + web_provider_livebox_delete_by_app_id(m_context.tzAppid.c_str()); + + if (ret < 0) { + _D("failed to delete box info"); + } else { + _D("delete box info: %s", m_context.tzAppid.c_str()); + } +} + +void TaskDbUpdate::StepRemoveExternalLocations() +{ + if (!m_context.removeAbnormal) { + WidgetDAO dao(DPL::FromUTF8String(m_context.tzAppid)); + _D("Removing external locations:"); + WrtDB::ExternalLocationList externalPaths = dao.getWidgetExternalLocations(); + FOREACH(file, externalPaths) + { + DPL::Utils::Path path(*file); + if(path.Exists()){ + if(path.IsFile()){ + _D(" -> %s", path.Fullpath().c_str()); + Try{ + DPL::Utils::Remove(path); + }Catch(DPL::Utils::Path::BaseException){ + _E("Failed to remove the file: %s", path.Fullpath().c_str()); + } + } else if (path.IsDir()){ + _D(" -> %s", path.Fullpath().c_str()); + Try{ + DPL::Utils::Remove(path); + }Catch(DPL::Utils::Path::BaseException){ + Throw(Jobs::WidgetUninstall::TaskDbUpdate:: + Exception::RemoveFilesFailed); + } + } + }else{ + _W(" -> %s(no such a path)", path.Fullpath().c_str()); + } + } + dao.unregisterAllExternalLocations(); + } +} + +void TaskDbUpdate::StartStep() +{ + _D("--------- : START ----------"); +} + +void TaskDbUpdate::EndStep() +{ + m_context.job->UpdateProgress( + UninstallerContext::UNINSTALL_DB_UPDATE, + "Widget DB Update Finished"); + + _D("--------- : END ----------"); +} +} //namespace WidgetUninstall +} //namespace Jobs diff --git a/src_mobile/jobs/widget_uninstall/task_db_update.h b/src_mobile/jobs/widget_uninstall/task_db_update.h new file mode 100644 index 0000000..3b74ad5 --- /dev/null +++ b/src_mobile/jobs/widget_uninstall/task_db_update.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file task_db_update.h + * @author Lukasz Wrzosek(l.wrzosek@samsung.com) + * @version 1.0 + * @brief Header file for uninstaller task database updating + */ + +#ifndef WRT_SRC_INSTALLER_CORE_JOB_WIDGET_UNINSTALL_TASK_DB_UPDATE_H_ +#define WRT_SRC_INSTALLER_CORE_JOB_WIDGET_UNINSTALL_TASK_DB_UPDATE_H_ + +#include +#include +#include + +class UninstallerContext; + +namespace Jobs { +namespace WidgetUninstall { +class TaskDbUpdate : + public DPL::TaskDecl +{ + class Exception + { + public: + DECLARE_EXCEPTION_TYPE(DPL::Exception, Base) + DECLARE_EXCEPTION_TYPE(Base, DbStepFailed) + DECLARE_EXCEPTION_TYPE(Base, RemoveFilesFailed) + }; + + UninstallerContext& m_context; + + private: + void StepDbUpdate(); + void StepLiveboxDBDelete(); + void StepRemoveExternalLocations(); + + void StartStep(); + void EndStep(); + + public: + TaskDbUpdate(UninstallerContext& context); + virtual ~TaskDbUpdate(); +}; +} //namespace WidgetUninstall +} //namespace Jobs + +#endif // WRT_SRC_INSTALLER_CORE_JOB_WIDGET_UNINSTALL_TASK_DB_UPDATE_H_ diff --git a/src_mobile/jobs/widget_uninstall/task_delete_pkginfo.cpp b/src_mobile/jobs/widget_uninstall/task_delete_pkginfo.cpp new file mode 100644 index 0000000..88db8e2 --- /dev/null +++ b/src_mobile/jobs/widget_uninstall/task_delete_pkginfo.cpp @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file task_delete_pkginfo.cpp + * @author Leerang Song(leerang.song@samsung.com) + * @version 1.0 + * @brief Implementation file for uninstaller delete package information + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Jobs { +namespace WidgetUninstall { +TaskDeletePkgInfo::TaskDeletePkgInfo( + UninstallerContext& context) : + DPL::TaskDecl(this), + m_context(context) +{ + AddStep(&TaskDeletePkgInfo::StartStep); + AddStep(&TaskDeletePkgInfo::StepDeletePkgInfo); + AddStep(&TaskDeletePkgInfo::EndStep); +} + +void TaskDeletePkgInfo::StartStep() +{ + _D("--------- : START ----------"); +} + +void TaskDeletePkgInfo::EndStep() +{ + _D("--------- : END ----------"); +} + +void TaskDeletePkgInfo::StepDeletePkgInfo() +{ + std::ostringstream manifest_name; + manifest_name << m_context.tzPkgid << ".xml"; + DPL::Utils::Path pre_manifest("/usr/share/packages"); + pre_manifest /= manifest_name.str(); + + if (!(m_context.manifestFile.Exists() == 0 && pre_manifest.Exists())) { + if (0 != pkgmgr_parser_parse_manifest_for_uninstallation( + m_context.manifestFile.Fullpath().c_str(), NULL)) { + _W("Manifest file failed to parse for uninstallation"); + } + } + if (!DPL::Utils::TryRemove(m_context.manifestFile)) { + _W("No manifest file found: %s", m_context.manifestFile.Fullpath().c_str()); + } else { + _D("Manifest file removed: %s", m_context.manifestFile.Fullpath().c_str()); + } +} +} //namespace WidgetUninstall +} //namespace Jobs diff --git a/src_mobile/jobs/widget_uninstall/task_delete_pkginfo.h b/src_mobile/jobs/widget_uninstall/task_delete_pkginfo.h new file mode 100644 index 0000000..4624c4a --- /dev/null +++ b/src_mobile/jobs/widget_uninstall/task_delete_pkginfo.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file task_delete_pkginfo.h + * @author Leerang Song(leerang.song@samsung.com) + * @version 1.0 + * @brief Header file for uninstaller task delete package infomation + */ + +#ifndef WRT_SRC_INSTALLER_CORE_JOB_WIDGET_UNINSTALL_TASK_DELETE_PKGINFO_H_ +#define WRT_SRC_INSTALLER_CORE_JOB_WIDGET_UNINSTALL_TASK_DELETE_PKGINFO_H_ + +#include +#include + +struct UninstallerContext; + +namespace Jobs { +namespace WidgetUninstall { +class TaskDeletePkgInfo : + public DPL::TaskDecl +{ + UninstallerContext& m_context; + + private: + void StepDeletePkgInfo(); + + void StartStep(); + void EndStep(); + + public: + TaskDeletePkgInfo(UninstallerContext& context); +}; +} //namespace WidgetUninstall +} //namespace Jobs + +#endif +// WRT_SRC_INSTALLER_CORE_JOB_WIDGET_UNINSTALL_TASK_DELETE_PKGINFO_H_ diff --git a/src_mobile/jobs/widget_uninstall/task_remove_custom_handlers.cpp b/src_mobile/jobs/widget_uninstall/task_remove_custom_handlers.cpp new file mode 100644 index 0000000..f981b0c --- /dev/null +++ b/src_mobile/jobs/widget_uninstall/task_remove_custom_handlers.cpp @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file task_remove_custom_handlers.cpp + * @author Przemyslaw Ciezkowski (p.ciezkowski@samsung.com) + * @version 1.0 + * @brief File for uninstaller - remove custom handlers + */ + +#include +#include +#include +#include +#include +#include +#include + +namespace Jobs { +namespace WidgetUninstall { +TaskRemoveCustomHandlers::TaskRemoveCustomHandlers(UninstallerContext& context) + : + DPL::TaskDecl(this), + m_context(context) +{ + AddStep(&TaskRemoveCustomHandlers::StartStep); + AddStep(&TaskRemoveCustomHandlers::Step); + AddStep(&TaskRemoveCustomHandlers::EndStep); +} + +void TaskRemoveCustomHandlers::Step() +{ + _D("Removing widget from appsvc"); + int result = appsvc_unset_defapp(m_context.tzAppid.c_str()); + _D("Result: %d", result); + + CustomHandlerDB::Interface::attachDatabaseRW(); + CustomHandlerDB::CustomHandlerDAO handlersDao( + DPL::FromASCIIString(m_context.tzAppid)); + handlersDao.removeWidgetProtocolHandlers(); + handlersDao.removeWidgetContentHandlers(); + CustomHandlerDB::Interface::detachDatabase(); +} + +void TaskRemoveCustomHandlers::StartStep() +{ + _D("--------- : START ----------"); +} + +void TaskRemoveCustomHandlers::EndStep() +{ + _D("--------- : END ----------"); +} +} //namespace WidgetUninstall +} //namespace Jobs diff --git a/src_mobile/jobs/widget_uninstall/task_remove_custom_handlers.h b/src_mobile/jobs/widget_uninstall/task_remove_custom_handlers.h new file mode 100644 index 0000000..e6458b9 --- /dev/null +++ b/src_mobile/jobs/widget_uninstall/task_remove_custom_handlers.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file task_remove_custom_handlers.h + * @author Przemyslaw Ciezkowski (p.ciezkowski@samsung.com) + * @version 1.0 + * @brief Header file for uninstaller - remove custom handlers + */ +#ifndef INSTALLER_CORE_JOBS_WIDGET_UNINSTALL_TASK_REMOVE_CUSTOM_HANDLERS_H +#define INSTALLER_CORE_JOBS_WIDGET_UNINSTALL_TASK_REMOVE_CUSTOM_HANDLERS_H + +#include + +class UninstallerContext; + +namespace Jobs { +namespace WidgetUninstall { +class TaskRemoveCustomHandlers : + public DPL::TaskDecl +{ + private: + UninstallerContext& m_context; + + void Step(); + + void StartStep(); + void EndStep(); + + public: + TaskRemoveCustomHandlers(UninstallerContext& context); +}; +} //namespace WidgetUninstall +} //namespace Jobs + +#endif /* INSTALLER_CORE_JOBS_WIDGET_UNINSTALL_TASK_REMOVE_CUSTOM_HANDLERS_H */ diff --git a/src_mobile/jobs/widget_uninstall/task_remove_files.cpp b/src_mobile/jobs/widget_uninstall/task_remove_files.cpp new file mode 100644 index 0000000..f9f22de --- /dev/null +++ b/src_mobile/jobs/widget_uninstall/task_remove_files.cpp @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file task_remove_files.cpp + * @author Lukasz Wrzosek(l.wrzosek@samsung.com) + * @version 1.0 + * @brief Implementation file for uninstaller task for removing widget files + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Jobs { +namespace WidgetUninstall { +using namespace WrtDB; + +TaskRemoveFiles::TaskRemoveFiles(UninstallerContext& context) : + DPL::TaskDecl(this), + m_context(context) +{ + AddStep(&TaskRemoveFiles::StartStep); + AddStep(&TaskRemoveFiles::StepRemoveInstallationDirectory); + AddStep(&TaskRemoveFiles::StepRemoveFinished); + AddStep(&TaskRemoveFiles::EndStep); +} + +TaskRemoveFiles::~TaskRemoveFiles() +{} + +void TaskRemoveFiles::StepRemoveInstallationDirectory() +{ + _D("StepRemoveInstallationDirectory started"); + Try { + int ret = app2ext_get_app_location(m_context.tzPkgid.c_str()); + + if (APP2EXT_SD_CARD == ret) { + _D("Remove external directory"); + Try { + WidgetInstallToExtSingleton::Instance().initialize(m_context.tzPkgid); + WidgetInstallToExtSingleton::Instance().uninstallation(); + WidgetInstallToExtSingleton::Instance().deinitialize(); + } + Catch(WidgetInstallToExt::Exception::ErrorInstallToExt) + { + // Continue uninstall even fail to remove external directory. + // i.e.) SD card isn't inserted or unmounted. + // This behavior is recommended by platform(app2sd maintainer). + _E("Fail to remove external directory"); + } + } + if (APP2EXT_NOT_INSTALLED != ret) { + _D("Removing directory"); + m_context.removeStarted = true; + DPL::Utils::Path widgetDir= m_context.installedPath; + Try{ + DPL::Utils::Remove(widgetDir); + } Catch(DPL::Utils::Path::BaseException){ + _E("Removing widget installation directory failed : %s", widgetDir.Fullpath().c_str()); + } + DPL::Utils::Path dataDir(m_context.locations->getUserDataRootDir()); + Try{ + DPL::Utils::Remove(dataDir); + } Catch(DPL::Utils::Path::BaseException){ + _W("%s is already removed", dataDir.Fullpath().c_str()); + } + } else { + _E("app is not installed"); + ThrowMsg(Exceptions::WidgetNotExist, "failed to get app location"); + } + } Catch(Exception::RemoveFilesFailed) { + ThrowMsg(Exceptions::RemoveFileFailure, "Cann't remove directory"); + } + m_context.job->UpdateProgress( + UninstallerContext::UNINSTALL_REMOVE_WIDGETDIR, + "Widget INstallation Directory Removal Finished"); +} + +void TaskRemoveFiles::StepRemoveFinished() +{ + _D("StepRemoveFinished finished"); + + m_context.job->UpdateProgress( + UninstallerContext::UNINSTALL_REMOVE_FINISHED, + "Widget remove steps Finished"); +} + +void TaskRemoveFiles::StartStep() +{ + _D("--------- : START ----------"); +} + +void TaskRemoveFiles::EndStep() +{ + _D("--------- : END ----------"); +} +} //namespace WidgetUninstall +} //namespace Jobs diff --git a/src_mobile/jobs/widget_uninstall/task_remove_files.h b/src_mobile/jobs/widget_uninstall/task_remove_files.h new file mode 100644 index 0000000..276fb24 --- /dev/null +++ b/src_mobile/jobs/widget_uninstall/task_remove_files.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file task_remove_files.h + * @author Lukasz Wrzosek(l.wrzosek@samsung.com) + * @version 1.0 + * @brief Header file for uninstaller task remove files + */ + +#ifndef WRT_SRC_INSTALLER_CORE_JOB_WIDGET_UNINSTALL_TASK_REMOVE_FILES_H_ +#define WRT_SRC_INSTALLER_CORE_JOB_WIDGET_UNINSTALL_TASK_REMOVE_FILES_H_ + +//forward declaration +struct UninstallerContext; + +#include +#include + +#include + +namespace Jobs { +namespace WidgetUninstall { +class TaskRemoveFiles : + public DPL::TaskDecl +{ + class Exception + { + public: + DECLARE_EXCEPTION_TYPE(DPL::Exception, Base) + DECLARE_EXCEPTION_TYPE(Base, RemoveFilesFailed) + }; + + UninstallerContext& m_context; + + private: + void StepRemoveInstallationDirectory(); + void StepRemoveFinished(); + + void StartStep(); + void EndStep(); + + public: + explicit TaskRemoveFiles(UninstallerContext& context); + virtual ~TaskRemoveFiles(); +}; +} //namespace WidgetUninstall +} //namespace Jobs + +#endif // WRT_SRC_INSTALLER_CORE_JOB_WIDGET_UNINSTALL_TASK_REMOVE_FILES_H_ diff --git a/src_mobile/jobs/widget_uninstall/task_smack.cpp b/src_mobile/jobs/widget_uninstall/task_smack.cpp new file mode 100644 index 0000000..e3471b3 --- /dev/null +++ b/src_mobile/jobs/widget_uninstall/task_smack.cpp @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file task_smack.cpp + * @author Piotr Kozbial (p.kozbial@samsung.com) + * @version 1.0 + * @brief Implementation file for installer task smack + */ + +#include +#include +#include +#include +#include + +#ifdef WRT_SMACK_ENABLED +#include +#endif + +namespace Jobs { +namespace WidgetUninstall { +TaskSmack::TaskSmack(UninstallerContext& context) : + DPL::TaskDecl(this), + m_context(context) +{ + AddStep(&TaskSmack::StartStep); + AddStep(&TaskSmack::Step); + AddStep(&TaskSmack::EndStep); +} + +void TaskSmack::Step() +{ + _D("------------------------> SMACK: Jobs::WidgetUninstall::TaskSmack::Step()"); +#ifdef WRT_SMACK_ENABLED + const char* pkgId = m_context.tzPkgid.c_str(); + if (PC_OPERATION_SUCCESS != perm_app_revoke_permissions(pkgId)) { + _E("failure in revoking smack permissions"); + } + + if (PC_OPERATION_SUCCESS != perm_app_uninstall(pkgId)) { + _E("failure in removing smack rules file"); + } +#endif +} + +void TaskSmack::StartStep() +{ + _D("--------- : START ----------"); +} + +void TaskSmack::EndStep() +{ + m_context.job->UpdateProgress( + UninstallerContext::UNINSTALL_SMACK_DISABLE, + "Widget SMACK Disabled"); + + _D("--------- : END ----------"); +} +} //namespace WidgetUninstall +} //namespace Jobs diff --git a/src_mobile/jobs/widget_uninstall/task_smack.h b/src_mobile/jobs/widget_uninstall/task_smack.h new file mode 100644 index 0000000..c7886b9 --- /dev/null +++ b/src_mobile/jobs/widget_uninstall/task_smack.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file task_smack.h + * @author Piotr Kozbial (p.kozbial@samsung.com) + * @version 1.0 + * @brief Header file for uninstaller task smack + */ +#ifndef INSTALLER_CORE_JOS_WIDGET_UNINSTALL_TASK_SMACK_H +#define INSTALLER_CORE_JOS_WIDGET_UNINSTALL_TASK_SMACK_H + +#include + +class UninstallerContext; + +namespace Jobs { +namespace WidgetUninstall { +class TaskSmack : + public DPL::TaskDecl +{ + private: + UninstallerContext& m_context; + + void Step(); + + void StartStep(); + void EndStep(); + + public: + TaskSmack(UninstallerContext& context); +}; +} //namespace WidgetUninstall +} //namespace Jobs + +#endif /* INSTALLER_CORE_JOS_WIDGET_UNINSTALL_TASK_SMACK_H */ diff --git a/src_mobile/jobs/widget_uninstall/task_uninstall_ospsvc.cpp b/src_mobile/jobs/widget_uninstall/task_uninstall_ospsvc.cpp new file mode 100644 index 0000000..10cf130 --- /dev/null +++ b/src_mobile/jobs/widget_uninstall/task_uninstall_ospsvc.cpp @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file task_uninstall_ospsvc.cpp + * @author Soyoung Kim(sy037.kim@samsung.com) + * @version 1.0 + * @brief Header file for widget uninstall task to uninstall ospsvc + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace WrtDB; + +namespace { +const int MAX_BUF_SIZE = 128; +const char* OSP_INSTALL_STR = "/usr/etc/package-manager/backend/tpk -uv "; +} + +namespace Jobs { +namespace WidgetUninstall { +TaskUninstallOspsvc::TaskUninstallOspsvc(UninstallerContext& context) : + DPL::TaskDecl(this), + m_context(context) +{ + AddStep(&TaskUninstallOspsvc::StartStep); + AddStep(&TaskUninstallOspsvc::StepUninstallOspsvc); + AddStep(&TaskUninstallOspsvc::EndStep); +} + +TaskUninstallOspsvc::~TaskUninstallOspsvc() +{} + +void TaskUninstallOspsvc::StepUninstallOspsvc() +{ + _D("Step : Uninstall Osp service"); + + std::ostringstream commStr; + commStr << OSP_INSTALL_STR << BashUtils::escape_arg(m_context.tzPkgid); + _D("osp uninstall command : %s", commStr.str().c_str()); + + char readBuf[MAX_BUF_SIZE]; + FILE *fd; + fd = popen(commStr.str().c_str(), "r"); + if (NULL == fd) { + _E("Failed to uninstalltion osp service"); + ThrowMsg(Exceptions::UninstallOspSvcFailed, + "Error occurs during\ + uninstall osp service"); + } + + if(fgets(readBuf, MAX_BUF_SIZE, fd) == NULL) + { + _E("Failed to uninstalltion osp service\ + Inability of reading file."); + ThrowMsg(Exceptions::UninstallOspSvcFailed, + "Error occurs during\ + uninstall osp service"); + } + _D("return value : %s", readBuf); + + int result = atoi(readBuf); + if (0 != result) { + ThrowMsg(Exceptions::UninstallOspSvcFailed, + "Error occurs during\ + install osp service"); + } + + pclose(fd); + + _D("Widget Can be uninstalled. Pkgname : %s", m_context.tzPkgid.c_str()); + m_context.job->UpdateProgress(UninstallerContext::UNINSTALL_REMOVE_OSPSVC, + "Uninstall OSP service finished"); +} + +void TaskUninstallOspsvc::StartStep() +{ + _D("--------- : START ----------"); +} + +void TaskUninstallOspsvc::EndStep() +{ + _D("--------- : END ----------"); +} +} //namespace WidgetUninstall +} //namespace Jobs diff --git a/src_mobile/jobs/widget_uninstall/task_uninstall_ospsvc.h b/src_mobile/jobs/widget_uninstall/task_uninstall_ospsvc.h new file mode 100644 index 0000000..50ec347 --- /dev/null +++ b/src_mobile/jobs/widget_uninstall/task_uninstall_ospsvc.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file task_uninstall_ospsvc.h + * @author Pawel Sikorski(p.sikorski@samsung.com) + * @version 1.0 + * @brief Header file for widget uninstall task to uninstall ospsvc + */ + +#ifndef WRT_SRC_INSTALLER_CORE_JOB_WIDGET_UNINSTALL_TASK_UNINSTALL_OSPSVC_H +#define WRT_SRC_INSTALLER_CORE_JOB_WIDGET_UNINSTALL_TASK_UNINSTALL_OSPSVC_H + +#include + +struct UninstallerContext; //forward declaration + +namespace Jobs { +namespace WidgetUninstall { +class TaskUninstallOspsvc : + public DPL::TaskDecl +{ + private: + //context + UninstallerContext& m_context; + + //steps + void StepUninstallOspsvc(); + + void StartStep(); + void EndStep(); + + public: + TaskUninstallOspsvc(UninstallerContext& context); + virtual ~TaskUninstallOspsvc(); +}; +} //namespace WidgetUninstall +} //namespace Jobs + +#endif /* WRT_SRC_INSTALLER_CORE_JOB_WIDGET_UNINSTALL_TASK_UNINSTALL_OSPSVC_H */ diff --git a/src_mobile/jobs/widget_uninstall/uninstaller_context.h b/src_mobile/jobs/widget_uninstall/uninstaller_context.h new file mode 100644 index 0000000..b6cf5bd --- /dev/null +++ b/src_mobile/jobs/widget_uninstall/uninstaller_context.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file uninstaller_context.h + * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com) + * @version + * @brief Definition file of installer tasks data structures + */ + +#ifndef WRT_SRC_INSTALLER_CORE_UNINSTALLER_TASKS_UNINSTALLER_CONTEXT_H_ +#define WRT_SRC_INSTALLER_CORE_UNINSTALLER_TASKS_UNINSTALLER_CONTEXT_H_ + +#include +#include +#include +#include + +namespace Jobs { +namespace WidgetUninstall { +class JobWidgetUninstall; +} //namespace WidgetUninstall +} //namespace Jobs + +struct UninstallerContext +{ + enum UninstallStep + { + UNINSTALL_START, + UNINSTALL_PRECHECK, + UNINSTALL_REMOVE_WIDGETDIR, + UNINSTALL_REMOVE_DESKTOP, + UNINSTALL_REMOVE_FINISHED, + UNINSTALL_DB_UPDATE, + UNINSTALL_REMOVE_OSPSVC, + UNINSTALL_SMACK_DISABLE, + UNINSTALL_END + }; + + ///< flag that indicates whether installer starts + //to remove files.rStruct; + bool removeStarted; + ///< flag that indicates whether installer finishes + //to remove files completely. + bool removeFinished; + + DPL::Optional locations; + + UninstallStep uninstallStep; ///< current step of installation + Jobs::WidgetUninstall::JobWidgetUninstall *job; + std::string tzAppid; + std::string tzPkgid; + bool removeAbnormal; + DPL::Utils::Path installedPath; + DPL::Utils::Path manifestFile; +}; + +#endif // WRT_SRC_INSTALLER_CORE_UNINSTALLER_TASKS_UNINSTALLER_CONTEXT_H_ diff --git a/src_mobile/jobs/widget_uninstall/widget_uninstall_errors.h b/src_mobile/jobs/widget_uninstall/widget_uninstall_errors.h new file mode 100644 index 0000000..3c5970b --- /dev/null +++ b/src_mobile/jobs/widget_uninstall/widget_uninstall_errors.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file widget_uninstall_errors.h + * @author Pawel Sikorski (p.sikorski@samgsung.com) + * @version + * @brief + */ + +#ifndef WIDGET_UNINSTALL_ERRORS_H_ +#define WIDGET_UNINSTALL_ERRORS_H_ + +#include +#include + +using namespace Jobs::Exceptions; + +namespace Jobs { +namespace WidgetUninstall { +namespace Exceptions { + +DECLARE_JOB_EXCEPTION_BASE(JobExceptionBase, Base, ErrorUnknown) + +DECLARE_JOB_EXCEPTION(Base, DatabaseFailure, ErrorWidgetUninstallationFailed) +DECLARE_JOB_EXCEPTION(Base, AlreadyUninstalling, + ErrorWidgetUninstallationFailed) +DECLARE_JOB_EXCEPTION(Base, AppIsRunning, ErrorWidgetUninstallationFailed) +DECLARE_JOB_EXCEPTION(Base, WidgetNotExist, ErrorWidgetUninstallationFailed) +DECLARE_JOB_EXCEPTION(Base, UninstallOspSvcFailed, + ErrorWidgetUninstallationFailed) +DECLARE_JOB_EXCEPTION(Base, PlatformAPIFailure, ErrorWidgetUninstallationFailed) +DECLARE_JOB_EXCEPTION(Base, RemoveFileFailure, ErrorWidgetUninstallationFailed) +DECLARE_JOB_EXCEPTION(Base, Unremovable, ErrorWidgetUninstallationFailed) +DECLARE_JOB_EXCEPTION(Base, CheckMDMPolicyFailure, ErrorWidgetUninstallationFailed) +} //namespace +} //namespace +} //namespace + +#endif /* WIDGET_UNINSTALL_ERRORS_H_ */ diff --git a/src_mobile/jobs/widget_uninstall/widget_uninstaller_struct.h b/src_mobile/jobs/widget_uninstall/widget_uninstaller_struct.h new file mode 100644 index 0000000..3f33e4b --- /dev/null +++ b/src_mobile/jobs/widget_uninstall/widget_uninstaller_struct.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file widget_uninstaller_struct.h + * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com) + * @version 1.0 + * @brief Implementation file for widget installer struct + */ +#ifndef WRT_SRC_INSTALLER_CORE_UNINSTALLER_TASKS_WIDGET_INSTALLER_STRUCT_H_ +#define WRT_SRC_INSTALLER_CORE_UNINSTALLER_TASKS_WIDGET_INSTALLER_STRUCT_H_ + +//SYSTEM INCLUDES +#include + +//WRT INCLUDES +#include +#include +#include +#include +#include + +//Widget Uninstaller typedefs +typedef void (*UninstallerFinishedCallback)( + void *userParam, + std::string tizenId, + Jobs::Exceptions::Type); + +typedef void (*UninstallerProgressCallback)( + void *userParam, + ProgressPercent percent, + const ProgressDescription &description); + +//UninstallationStruct +typedef Jobs::JobCallbacksBase +WidgetUninstallCallbackBase; + +struct WidgetUninstallationStruct : public WidgetUninstallCallbackBase +{ + std::shared_ptr pkgmgrInterface; + + // It must be empty-constructible as a parameter of generic event + WidgetUninstallationStruct() + {} + + WidgetUninstallationStruct( + UninstallerFinishedCallback finished, + UninstallerProgressCallback progress, + void *param, + std::shared_ptr + _pkgmgrInterface + ) : + WidgetUninstallCallbackBase(finished, progress, param), + pkgmgrInterface(_pkgmgrInterface) + {} +}; +#endif // WRT_SRC_INSTALLER_CORE_UNINSTALLER_TASKS_WIDGET_INSTALLER_STRUCT_H_ diff --git a/src_mobile/logic/installer_controller.cpp b/src_mobile/logic/installer_controller.cpp new file mode 100644 index 0000000..d9b41d5 --- /dev/null +++ b/src_mobile/logic/installer_controller.cpp @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "installer_controller.h" +#include + +IMPLEMENT_SINGLETON(Logic::InstallerController) + +namespace Logic { +InstallerController::InstallerController() +{} + +void InstallerController::OnEventReceived( + const InstallerControllerEvents::InstallWidgetEvent &event) +{ + std::string fileName = event.GetArg0(); + std::string pkgId = event.GetArg1(); + Jobs::WidgetInstall::WidgetInstallationStruct installerStruct = event.GetArg2(); + m_installerLogic.InstallWidget(fileName, pkgId, installerStruct); +} + +void InstallerController::OnEventReceived( + const InstallerControllerEvents::InstallPluginEvent &event) +{ + std::string dirName = event.GetArg0(); + PluginInstallerStruct installerStruct = event.GetArg1(); + m_installerLogic.InstallPlugin(dirName, installerStruct); +} + +void InstallerController::OnEventReceived( + const InstallerControllerEvents::UninstallWidgetEvent &event) +{ + std::string widgetPkgName = event.GetArg0(); + WidgetUninstallationStruct uninstallerStruct = event.GetArg1(); + m_installerLogic.UninstallWidget(widgetPkgName, uninstallerStruct); +} + +Eina_Bool InstallerController::AddNextStep(void *data) +{ + Jobs::Job* model = static_cast(data); + CONTROLLER_POST_EVENT(InstallerController, + InstallerControllerEvents::NextStepEvent(model)); + + return ECORE_CALLBACK_CANCEL; +} + +void InstallerController::OnEventReceived( + const InstallerControllerEvents::NextStepEvent &event) +{ + Jobs::Job* model = event.GetArg0(); + Assert(model != NULL); + + if (m_installerLogic.NextStep(model)) { + ecore_idler_add(AddNextStep, model); + } +} + +void InstallerController::OnEventReceived( + const InstallerControllerEvents::InitializeEvent & /*event*/) +{ + m_installerLogic.Initialize(); +} + +void InstallerController::OnEventReceived( + const InstallerControllerEvents::TerminateEvent & /*event*/) +{ + m_installerLogic.Terminate(); +} +} //Logic + diff --git a/src_mobile/logic/installer_controller.h b/src_mobile/logic/installer_controller.h new file mode 100644 index 0000000..9f04288 --- /dev/null +++ b/src_mobile/logic/installer_controller.h @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef WRT_SRC_INSTALLER_CORE_INSTALLER_CONTROLLER_H_ +#define WRT_SRC_INSTALLER_CORE_INSTALLER_CONTROLLER_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * @brief holds events send to InstallControler + */ +namespace InstallerControllerEvents { +/** + * @brief Event for inicieting instalation process. + * + * This event holds std::string witch should be path to widget package + */ +DECLARE_GENERIC_EVENT_3(InstallWidgetEvent, + std::string, // zipFileName + std::string, // package id + Jobs::WidgetInstall::WidgetInstallationStruct) // installerStruct + +/** + * @brief Event for iniciating plugin instalation process. + * This event holds std::string witch should be path to plugin directory + * and PluginInstallerStruct which contain + * StatusCallack, progressCallback and private data for callbacks + */ +DECLARE_GENERIC_EVENT_2(InstallPluginEvent, std::string, PluginInstallerStruct) + +/** + * @brief Event for inicietig widget uninstallation. + * + * tizen id is used to point witch widget shuld be uninstalled + */ +DECLARE_GENERIC_EVENT_2(UninstallWidgetEvent, + std::string, + WidgetUninstallationStruct) + +/** + * @brief Event for pushing installation process forward. + */ +DECLARE_GENERIC_EVENT_1(NextStepEvent, Jobs::Job *) + +DECLARE_GENERIC_EVENT_0(InitializeEvent) +DECLARE_GENERIC_EVENT_0(TerminateEvent) +} // namespace InstallerEvents + +namespace Logic { +/** + * @brief Controls Widget installation + * + * Main Controler of wiget installation/uninstallation, this is also used + * for pushing forward each of processes. + * It waits for three events: + *
    + *
  • InstallWidgetEvent
  • + *
  • UninstallWidgetEvent
  • + *
  • NextStepEvent
  • + *
+ */ + +typedef DPL::TypeListDecl< + InstallerControllerEvents::InstallWidgetEvent, + InstallerControllerEvents::InstallPluginEvent, + InstallerControllerEvents::UninstallWidgetEvent, + InstallerControllerEvents::NextStepEvent, + InstallerControllerEvents::InitializeEvent, + InstallerControllerEvents::TerminateEvent>::Type +InstallerControllerEventsSet; + +class InstallerController : public DPL::Event::Controller< + InstallerControllerEventsSet> +{ + protected: + /** + * @brief Executed on InstallWidgetEvent received. + */ + virtual void OnEventReceived( + const InstallerControllerEvents::InstallWidgetEvent &event); + + /** + * @brief Executed on InstallPluginEvent received. + */ + virtual void OnEventReceived( + const InstallerControllerEvents::InstallPluginEvent &event); + + /** + * @brief Executed on UninstallWidgetEvent received. + */ + virtual void OnEventReceived( + const InstallerControllerEvents::UninstallWidgetEvent &event); + /** + * @brief Executed on NextStepEvent received. + */ + virtual void OnEventReceived( + const InstallerControllerEvents::NextStepEvent &event); + + virtual void OnEventReceived( + const InstallerControllerEvents::InitializeEvent &event); + virtual void OnEventReceived( + const InstallerControllerEvents::TerminateEvent &event); + + private: + // Embedded logic + Logic::InstallerLogic m_installerLogic; + + InstallerController(); + + static Eina_Bool AddNextStep(void *data); + + friend class DPL::Singleton; +}; + +typedef DPL::Singleton InstallerControllerSingleton; +} + +#endif // INSTALLER_CONTROLLER_H diff --git a/src_mobile/logic/installer_logic.cpp b/src_mobile/logic/installer_logic.cpp new file mode 100644 index 0000000..df67764 --- /dev/null +++ b/src_mobile/logic/installer_logic.cpp @@ -0,0 +1,254 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace WrtDB; + +namespace Logic { +InstallerLogic::InstallerLogic() : + m_job(0), + m_NextHandle(0) +{} + +InstallerLogic::~InstallerLogic() +{ + Assert(!m_job && "There are still running job"); + //FIXME what should be done here? +} + +void InstallerLogic::Initialize() +{ + _D("Done"); +} + +void InstallerLogic::Terminate() +{ + //TODO how to delete, if it is still running, paused and so on + if(m_job) + m_job->SetPaused(true); + + _D("Done"); +} + +Jobs::JobHandle InstallerLogic::AddAndStartJob() +{ + Jobs::JobHandle handle = GetNewJobHandle(); + m_job->SetJobHandle(handle); + //Start job + CONTROLLER_POST_EVENT(InstallerController, + InstallerControllerEvents::NextStepEvent(m_job)); + + return handle; +} + +//InstallWidget, UninstallWidget InstallPlugin method are almost the same +// But each Job has different constructor, so creating new Job is specific +Jobs::JobHandle InstallerLogic::InstallWidget( + const std::string & widgetPath, + const std::string & pkgId, + const Jobs::WidgetInstall::WidgetInstallationStruct & + installerStruct) +{ + if(m_job) + { + _E("Job is in progress. It is impossible to add new job"); + return -1; + } + + _D("New Widget Installation:"); + + m_job = new Jobs::WidgetInstall::JobWidgetInstall(widgetPath, pkgId, installerStruct); + + return AddAndStartJob(); +} + +Jobs::JobHandle InstallerLogic::UninstallWidget( + const std::string & widgetPkgName, + const + WidgetUninstallationStruct &uninstallerStruct) +{ + if(m_job) + { + _E("Job is in progress. It is impossible to add new job"); + return -1; + } + + _D("New Widget Uninstallation"); + + m_job = + new Jobs::WidgetUninstall::JobWidgetUninstall(widgetPkgName, + uninstallerStruct); + + return AddAndStartJob(); +} + +Jobs::JobHandle InstallerLogic::InstallPlugin( + std::string const & pluginPath, // TODO change type to PluginPath + const PluginInstallerStruct & + installerStruct) +{ + if(m_job) + { + _E("Job is in progress. It is impossible to add new job"); + return -1; + } + + _D("New Plugin Installation"); + + // TODO Conversion to PluginPath is temporary + m_job = + new Jobs::PluginInstall::JobPluginInstall(PluginPath(pluginPath), installerStruct); + + // before start install plugin, reset plugin data which is stopped + // during installing. (PluginDAO::INSTALLATION_IN_PROGRESS) + ResetProgressPlugins(); + + return AddAndStartJob(); +} + +#define TRANSLATE_JOB_EXCEPTION() \ + _rethrown_exception.getParam() +#define TRANSLATE_JOB_MESSAGE() \ + _rethrown_exception.GetMessage() + +bool InstallerLogic::NextStep(Jobs::Job *job) +{ + Try { + bool stepSucceded = job->NextStep(); + + job->SendProgress(); + + if (stepSucceded) { + return !job->IsPaused(); + } + + if (!job->GetAbortStarted()) { + //job successfully finished + + //send finished callback + job->SendFinishedSuccess(); + + switch (job->GetInstallationType()) { + case Jobs::PluginInstallation: + InstallWaitingPlugins(); + break; + default: //because of warning + break; + } + } else { + //job abort process completed + job->SendFinishedFailure(); + } + + //clean job + delete job; + m_job=0; + + return false; + } catch (Jobs::JobExceptionBase &exc) { + //start revert job + _D("Exception occured: %d. Reverting job...", exc.getParam()); + bool hasAbortSteps = job->Abort(); + job->SetAbortStarted(true); + job->SaveExceptionData(exc); + + if (!hasAbortSteps) { + //no AbortSteps + job->SendFinishedFailure(); + + //clean job + delete job; + m_job=0; + } + return hasAbortSteps; + } +} + +void InstallerLogic::InstallWaitingPlugins() +{ + PluginHandleSetPtr waitingPlugins; + + waitingPlugins = + PluginDAO::getPluginHandleByStatus(PluginDAO::INSTALLATION_WAITING); + + FOREACH(it, *waitingPlugins) + { + resolvePluginDependencies(*it); + } +} + +void InstallerLogic::ResetProgressPlugins() +{ + PluginHandleSetPtr progressPlugins; + + progressPlugins = + PluginDAO::getPluginHandleByStatus(PluginDAO::INSTALLATION_IN_PROGRESS); + + FOREACH(it, *progressPlugins) { + FeatureHandleListPtr featureListPtr = + FeatureDAOReadOnly::GetFeatureHandleListForPlugin(*it); + FOREACH(ItFeature, *featureListPtr) { + FeatureDAO::UnregisterFeature(*ItFeature); + } + PluginDAO::unregisterPlugin(*it); + } +} + +bool InstallerLogic::resolvePluginDependencies(PluginHandle handle) +{ + PluginHandleSetPtr dependencies(new PluginHandleSet); + + PluginObjects::ObjectsPtr requiredObjects = + PluginDAO::getRequiredObjectsForPluginHandle(handle); + + PluginHandle depHandle = + Jobs::PluginInstall::JobPluginInstall::INVALID_HANDLE; + + FOREACH(requiredObject, *requiredObjects) + { + depHandle = + PluginDAO::getPluginHandleForImplementedObject(*requiredObject); + + if (depHandle == + Jobs::PluginInstall::JobPluginInstall::INVALID_HANDLE) + { + _E("Library implementing: %s NOT FOUND", (*requiredObject).c_str()); + + //PluginDAO::SetPluginInstallationStatus(INSTALLATION_WAITING); + return false; + } + dependencies->insert(depHandle); + } + + PluginDAO::registerPluginLibrariesDependencies(handle, dependencies); + PluginDAO::setPluginInstallationStatus(handle, + PluginDAO::INSTALLATION_COMPLETED); + + return true; +} +} + diff --git a/src_mobile/logic/installer_logic.h b/src_mobile/logic/installer_logic.h new file mode 100644 index 0000000..abe1b5c --- /dev/null +++ b/src_mobile/logic/installer_logic.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef WRT_SRC_INSTALLER_CORE_INSTALLER_LOGIC_H_ +#define WRT_SRC_INSTALLER_CORE_INSTALLER_LOGIC_H_ + +#include +#include +#include +#include +#include +#include +#include + +namespace Logic { +class InstallerLogic +{ + Jobs::Job* m_job; + + void ResetProgressPlugins(); + void InstallWaitingPlugins(); + bool resolvePluginDependencies(PluginHandle handle); + + Jobs::JobHandle m_NextHandle; + Jobs::JobHandle GetNewJobHandle() + { + return m_NextHandle++; + } + Jobs::JobHandle AddAndStartJob(); + + public: + virtual ~InstallerLogic(); + + void Initialize(); + + void Terminate(); + + Jobs::JobHandle InstallWidget( + const std::string & widgetPath, + const std::string & pkgId, + const Jobs::WidgetInstall::WidgetInstallationStruct & + installerStruct); + + Jobs::JobHandle UninstallWidget( + const std::string & widgetPkgName, + const WidgetUninstallationStruct & + uninstallerStruct); + + Jobs::JobHandle InstallPlugin(std::string const & pluginPath, + const PluginInstallerStruct &installerStruct); + + bool NextStep(Jobs::Job* installModel); + + //TODO implement me + bool AbortJob(const Jobs::JobHandle & /*handle*/) + { + _W("Not implemented"); + return true; + } + + private: + InstallerLogic(); + + friend class InstallerController; +}; +} + +#endif // INSTALLER_LOGIC_H diff --git a/src_mobile/misc/feature_logic.cpp b/src_mobile/misc/feature_logic.cpp new file mode 100644 index 0000000..818b0cd --- /dev/null +++ b/src_mobile/misc/feature_logic.cpp @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "feature_logic.h" + +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace Jobs { +namespace WidgetInstall { +namespace { +const DPL::String PRIVILEGE_TESTAUTOMATION = + L"http://tizen.org/privilege/testautomation"; +const DPL::String DEVICE_CAPABILITY_TESTAUTOMATION = L"testautomation"; +} +FeatureLogic::FeatureLogic(const WrtDB::TizenAppId & tzAppid) : + m_rejected(false) +{ + WrtDB::WidgetDAOReadOnly widgetDao(tzAppid); + WidgetFeatureSet featureSet = widgetDao.getFeaturesList(); + FOREACH(it, featureSet) { + _D("Feature name : %ls", it->name.c_str()); + WrtDB::DeviceCapabilitySet dcs; + if (!DPL::StringCompare(it->name, PRIVILEGE_TESTAUTOMATION)) { + // special privilege + // This privilege doesn't have plugin in the target + // only use to special behavior + dcs.insert(DEVICE_CAPABILITY_TESTAUTOMATION); + } else { + // normal privilege + dcs = WrtDB::FeatureDAOReadOnly::GetDeviceCapability(it->name); + } + FOREACH(devCap, dcs) { + _D("--- dev cap : %ls", (*devCap).c_str()); + } + Feature feature(*it, dcs); + m_featureList.push_back(feature); + } + m_currentFeature = m_featureList.begin(); + + // ok we must set iterator on the first processable node + if (!isProcessable()) { + next(); + } +} + +bool FeatureLogic::isDone() const +{ + return m_currentFeature == m_featureList.end(); +} + +bool FeatureLogic::next() +{ + while (!isDone()) { + if (m_currentFeature->currentCap != + m_currentFeature->devCapSet.end()) + { + m_currentFeature->currentCap++; + } else { + ++m_currentFeature; + } + // we moved pointer + if (isProcessable()) { + return true; + } + } + return false; +} + +void FeatureLogic::setAceResponse(bool allowed) +{ + Assert(isProcessable() && "Wrong usage"); + if (!allowed) { + m_currentFeature->rejected = true; + m_rejected = true; + } +} + +DPL::String FeatureLogic::getDevice() const +{ + return *(m_currentFeature->currentCap); +} + +bool FeatureLogic::isProcessable() const +{ + if (isDone()) { + return false; + } + + if (m_currentFeature->currentCap == m_currentFeature->devCapSet.end()) { + return false; + } + + return true; +} +} // namespace WidgetInstall +} // namespace Jobs + diff --git a/src_mobile/misc/feature_logic.h b/src_mobile/misc/feature_logic.h new file mode 100644 index 0000000..d407cb0 --- /dev/null +++ b/src_mobile/misc/feature_logic.h @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SRC_INSTALLER_MISC_FEATURE_LOGIC +#define SRC_INSTALLER_MISC_FEATURE_LOGIC + +#include +#include + +#include +#include +#include + +#include +#include + +namespace Jobs { +namespace WidgetInstall { +class FeatureLogic : DPL::Noncopyable +{ + public: + + FeatureLogic(const WrtDB::TizenAppId & tzAppid); + + bool isDone() const; + + bool next(); + + void setAceResponse(bool allowed); + + DPL::String getDevice() const; + + bool isRejected(void) const + { + return m_rejected; + } + + struct Feature : public WidgetFeature { + WrtDB::DeviceCapabilitySet devCapSet; + WrtDB::DeviceCapabilitySet::const_iterator currentCap; + + Feature(const WidgetFeature &wf, + const WrtDB::DeviceCapabilitySet &set) : + WidgetFeature(wf) + , devCapSet(set) + { + currentCap = devCapSet.begin(); + } + + explicit Feature(const Feature &second) : WidgetFeature(second) + { + devCapSet = second.devCapSet; + currentCap = devCapSet.find(*second.currentCap); + rejected = second.rejected; + } + + private: + void operator=(const Feature &second) + { + name = second.name; + devCapSet = second.devCapSet; + rejected = second.rejected; + pluginId = second.pluginId; + currentCap = devCapSet.find(*second.currentCap); + } + }; + + typedef std::list FeatureList; + typedef FeatureList::const_iterator FeatureIterator; + + FeatureIterator resultBegin() + { + return m_featureList.begin(); + } + FeatureIterator resultEnd() + { + return m_featureList.end(); + } + + private: + bool isProcessable() const; + + FeatureList m_featureList; + FeatureList::iterator m_currentFeature; + bool m_rejected; +}; + +typedef std::shared_ptr FeatureLogicPtr; +} // namespace WidgetInstall +} // namespace Jobs + +#endif // SRC_INSTALLER_MISC_FEATURE_LOGIC diff --git a/src_mobile/misc/libxml_utils.cpp b/src_mobile/misc/libxml_utils.cpp new file mode 100644 index 0000000..114e95b --- /dev/null +++ b/src_mobile/misc/libxml_utils.cpp @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file libxml_utils.cpp + * @author Tomasz Iwanek (t.iwanek@samsung.com) + */ + +#include "libxml_utils.h" + +#include +#include + +IMPLEMENT_SINGLETON(LibxmlUtils) + +LibxmlUtils::LibxmlUtils() : isInitialized(false) +{} + +LibxmlUtils::~LibxmlUtils() +{ + if (isInitialized) { + _D("Libxml - cleaning"); + // Cleanup function for the XML library. + xmlCleanupParser(); + //this is to debug memory for regression tests + xmlMemoryDump(); + } +} + +void LibxmlUtils::init() +{ + if (!isInitialized) { + LIBXML_TEST_VERSION + isInitialized = true; + _D("Libxml have been initialized"); + } + _D("Libxml already initialized"); +} + diff --git a/src_mobile/misc/libxml_utils.h b/src_mobile/misc/libxml_utils.h new file mode 100644 index 0000000..5354bda --- /dev/null +++ b/src_mobile/misc/libxml_utils.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file libxml_utils.h + * @author Tomasz Iwanek (t.iwanek@samsung.com) + */ + +#ifndef LIBXML_UTILS_H +#define LIBXML_UTILS_H + +#include +#include + +#include +#include +#include +#include + +/** + * @brief The LibxmlUtils class + * + * Singleton for assurence for libxml2 initialization + * + * Use: LibxmlUtils::Instance().init(); to initialize library + * + */ +class LibxmlUtils +{ + public: + DECLARE_EXCEPTION_TYPE(DPL::Exception, Base) + DECLARE_EXCEPTION_TYPE(Base, Libxml2Error) + + LibxmlUtils(); + ~LibxmlUtils(); + + void init(); + + private: + bool isInitialized; + + friend class DPL::Singleton; +}; + +typedef DPL::Singleton LibxmlSingleton; + +#endif // LIBXML_UTILS_H diff --git a/src_mobile/misc/plugin_path.cpp b/src_mobile/misc/plugin_path.cpp new file mode 100644 index 0000000..2b2ebdb --- /dev/null +++ b/src_mobile/misc/plugin_path.cpp @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file plugin_path_builder.cpp + * @author Kamil Nować (k.nowac@partner.samgsung.com) + * @version + * @brief + */ + +#include +#include +#include + +using namespace DPL::Utils; + +PluginPath::PluginPath(const Path& fullPath) : Path(fullPath.Fullpath()) +{ + setLibraryCombinedName( + WrtDB::GlobalConfig::GetPluginPrefix(), + WrtDB::GlobalConfig::GetPluginSuffix()); +}; +PluginPath::PluginPath(const std::string& fullPath) : Path(fullPath) +{ + setLibraryCombinedName( + WrtDB::GlobalConfig::GetPluginPrefix(), + WrtDB::GlobalConfig::GetPluginSuffix()); +}; +PluginPath::PluginPath(const DPL::String& fullPath) : Path(fullPath) +{ + setLibraryCombinedName( + WrtDB::GlobalConfig::GetPluginPrefix(), + WrtDB::GlobalConfig::GetPluginSuffix()); +}; +PluginPath::PluginPath(){} + +PluginPath PluginPath::getMetaFile() const +{ + PluginPath metaFile = *this; + return metaFile /= WrtDB::GlobalConfig::GetPluginMetafileName(); +} \ No newline at end of file diff --git a/src_mobile/misc/plugin_path.h b/src_mobile/misc/plugin_path.h new file mode 100644 index 0000000..8ada790 --- /dev/null +++ b/src_mobile/misc/plugin_path.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file plugin_path_builder.cpp + * @author Kamil Nować (k.nowac@partner.samgsung.com) + * @version + * @brief + */ + +#ifndef PLUGIN_PATH_H +#define PLUGIN_PATH_H + +#include +#include +#include + +class PluginPath: public DPL::Utils::Path{ +private: + std::string m_library; + +public: + PluginPath(const DPL::Utils::Path& fullPath); + PluginPath(const std::string& fullPath); + PluginPath(const DPL::String& fullPath); + PluginPath(); + + //getMetafile() this function adds metafile to current path. + PluginPath getMetaFile() const; + + //setLibraryCombinedName This function creates name for library by adding + //prefix and suffix to PluginPath object filename. + void setLibraryCombinedName(const std::string& prefix, const std::string& sufix) + { + this->m_library = prefix + this->Filename() + sufix; + } + + //getLibraryName returns library name + const std::string& getLibraryName() const + { + return m_library; + } + //getLibraryPath returns full path to the library + const PluginPath getLibraryPath() const + { + return this->operator /(m_library); + } +}; + +#endif // PLUGIN_PATH_H diff --git a/src_mobile/misc/wac_widget_id.cpp b/src_mobile/misc/wac_widget_id.cpp new file mode 100644 index 0000000..b24679a --- /dev/null +++ b/src_mobile/misc/wac_widget_id.cpp @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file + * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com) + * @version 1.0 + * @brief + */ +#include "wac_widget_id.h" + +#include +#include + +#include + +#include +#include + +namespace { +const char *SCHEME_HTTP = "http"; +const char *SCHEME_HTTPS = "https"; +} + +WacWidgetId::WacWidgetId(const DPL::OptionalString &widgetId) : + m_schemaMatch(false) +{ + if (!widgetId.IsNull()) { + std::string wid = DPL::ToUTF8String(*widgetId); + parse(wid.c_str()); + } +} + +bool WacWidgetId::matchHost(const DPL::String &second) const +{ + _D("m_schemaMatch is: %d", m_schemaMatch); + if (!m_schemaMatch) { + return false; + } + + _D("Matching DNS identity: %s %ls", m_host.c_str(), second.c_str()); + + return m_host == DPL::ToUTF8String(second); +} + +void WacWidgetId::parse(const char *url) +{ + _D("Widget id to parse: %s", url); + + std::unique_ptr > + iri(iri_parse(url), iri_destroy); + + if (!iri.get()) { + _E("Error in parsing widget id."); + return; // m_schemaMatch == false; + } + + std::string scheme; + + if (iri.get()->scheme) { + scheme = iri.get()->scheme; + } else { + _W("Error. No scheme in widget id."); + return; // m_schemaMatch == false; + } + + // should we support HTTP and HTTPS? wac says nothing + // std::transform(m_scheme.begin(), m_scheme.end(), m_scheme.begin(), + // tolower); + + // We only match "http" and "https" schemas + if ((scheme != SCHEME_HTTP) && (scheme != SCHEME_HTTPS)) { + _W("Unknown scheme in widget id. %s", scheme.c_str()); + return; // m_schemaMatch == false; + } else { + m_schemaMatch = true; + } + + if (iri.get()->host) { + m_host = iri.get()->host; + _D("Host has been set to: %s", m_host.c_str()); + } + + // What to do when host is empty? No info in wac documentation. + + // Any post processing algorithm? No info in wac documentation. +} diff --git a/src_mobile/misc/wac_widget_id.h b/src_mobile/misc/wac_widget_id.h new file mode 100644 index 0000000..dba5f36 --- /dev/null +++ b/src_mobile/misc/wac_widget_id.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file + * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com) + * @version 1.0 + * @brief + */ +#ifndef WRT_ENGINE_SRC_INSTALLER_CORE_MISC_WAC_WIDGET_ID_H +#define WRT_ENGINE_SRC_INSTALLER_CORE_MISC_WAC_WIDGET_ID_H + +#include +#include + +class WacWidgetId +{ + public: + explicit WacWidgetId(const DPL::OptionalString &widgetId); + bool matchHost(const DPL::String &second) const; + + private: + void parse(const char *url); + + bool m_schemaMatch; + std::string m_host; +}; + +#endif // WRT_ENGINE_SRC_INSTALLER_CORE_MISC_WAC_WIDGET_ID_H + diff --git a/src_mobile/misc/widget_install_to_external.cpp b/src_mobile/misc/widget_install_to_external.cpp new file mode 100644 index 0000000..b0219dd --- /dev/null +++ b/src_mobile/misc/widget_install_to_external.cpp @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file widget_install_to_external.cpp + * @author Soyoung Kim (sy037.kim@smasung.com) + */ +#include "widget_install_to_external.h" + +#include +#include +#include + +IMPLEMENT_SAFE_SINGLETON(WidgetInstallToExt) + +WidgetInstallToExt::WidgetInstallToExt() : + m_handle(NULL), + m_appId("") +{} + +WidgetInstallToExt::~WidgetInstallToExt() +{} + +void WidgetInstallToExt::initialize(std::string appId) +{ + _D("WidgetInstallToExt::initialize()"); + m_appId = appId; + + if (NULL == m_handle) { + m_handle = app2ext_init(APP2EXT_SD_CARD); + if (NULL == m_handle) { + ThrowMsg(Exception::ErrorInstallToExt, "initialize failed"); + } + } +} + +void WidgetInstallToExt::deinitialize() +{ + _D("WidgetInstallToExt::deinitialize()"); + if (NULL != m_handle) { + if (0 < app2ext_deinit(m_handle)) { + ThrowMsg(Exception::ErrorInstallToExt, + "app2ext deinitialize \ + failed"); + } + } +} + +void WidgetInstallToExt::preInstallation(GList *dirList, int dSize) +{ + _D("WidgetInstallToExt::preInstallation()"); + Assert(m_handle); + + int ret = m_handle->interface.pre_install(m_appId.c_str(), dirList, dSize); + + if (APP2EXT_SUCCESS == ret) { + _D("App2Ext pre install success"); + } else { + postInstallation(false); + ThrowMsg(Exception::ErrorInstallToExt, "pre-install failed"); + } +} + +void WidgetInstallToExt::postInstallation(bool status) +{ + _D("WidgetInstallToExt::postInstallation()"); + + if (NULL != m_handle) { + if (status) { + m_handle->interface.post_install(m_appId.c_str(), + APP2EXT_STATUS_SUCCESS); + } else { + m_handle->interface.post_install(m_appId.c_str(), + APP2EXT_STATUS_FAILED); + } + } +} + +void WidgetInstallToExt::preUpgrade(GList *dirList, int dSize) +{ + _D("WidgetInstallToExt::preUpgrade()"); + Assert(m_handle); + + int ret = m_handle->interface.pre_upgrade(m_appId.c_str(), dirList, dSize); + if (APP2EXT_SUCCESS == ret) { + _D("App2Ext pre-upgrade success"); + } else { + postUpgrade(false); + ThrowMsg(Exception::ErrorInstallToExt, "pre-upgrade failed"); + } +} + +void WidgetInstallToExt::postUpgrade(bool status) +{ + _D("WidgetInstallToExt::postUpgrade()"); + if (NULL != m_handle) { + if (status) { + m_handle->interface.post_upgrade(m_appId.c_str(), + APP2EXT_STATUS_SUCCESS); + } else { + m_handle->interface.post_upgrade(m_appId.c_str(), + APP2EXT_STATUS_FAILED); + } + } +} + +void WidgetInstallToExt::uninstallation() +{ + _D("WidgetInstallToExt::uninstallation()"); + + Assert(m_handle); + + int ret = m_handle->interface.pre_uninstall(m_appId.c_str()); + if (APP2EXT_SUCCESS == ret) { + if (APP2EXT_SUCCESS == + m_handle->interface.post_uninstall(m_appId.c_str())) + { + _D("App2Ext pre-uninstall success"); + } else { + ThrowMsg(Exception::ErrorInstallToExt, "post-uninstall failed"); + } + } else { + ThrowMsg(Exception::ErrorInstallToExt, "pre-uninstall failed"); + } +} + +void WidgetInstallToExt::disable() +{ + _D("WidgetInstallToExt::disable()"); + if (NULL != m_handle) { + int ret = m_handle->interface.disable(m_appId.c_str()); + if (APP2EXT_SUCCESS != ret && APP2EXT_ERROR_UNMOUNT != ret) { + ThrowMsg(Exception::ErrorInstallToExt, "disable failed"); + } + } +} diff --git a/src_mobile/misc/widget_install_to_external.h b/src_mobile/misc/widget_install_to_external.h new file mode 100644 index 0000000..cc9c4df --- /dev/null +++ b/src_mobile/misc/widget_install_to_external.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file widget_install_to_external.h + * @author Soyoung Kim (sy037.kim@smasung.com) + */ +#ifndef WRT_INSTALLER_SRC_MISC_WIDGET_INSTALL_TO_EXTERNAL_H +#define WRT_INSTALLER_SRC_MISC_WIDGET_INSTALL_TO_EXTERNAL_H + +#include +#include +#include +#include + +class WidgetInstallToExt +{ + public: + class Exception + { + public: + DECLARE_EXCEPTION_TYPE(DPL::Exception, Base) + DECLARE_EXCEPTION_TYPE(Base, ErrorInstallToExt) + }; + + void initialize(std::string appId); + void deinitialize(); + void preInstallation(GList* dirList, int dSize); + void postInstallation(bool status); + void preUpgrade(GList* dirList, int dSize); + void postUpgrade(bool status); + void uninstallation(); + void disable(); + + private: + app2ext_handle *m_handle; + std::string m_appId; + + WidgetInstallToExt(); + ~WidgetInstallToExt(); + + friend class DPL::Singleton; +}; + +typedef DPL::Singleton WidgetInstallToExtSingleton; + +#endif // WRT_INSTALLER_SRC_MISC_WIDGET_INSTALL_TO_EXTERNAL_H diff --git a/src_mobile/misc/widget_location.cpp b/src_mobile/misc/widget_location.cpp new file mode 100644 index 0000000..182df80 --- /dev/null +++ b/src_mobile/misc/widget_location.cpp @@ -0,0 +1,277 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file widget_location.cpp + * @author Iwanek Tomasz (t.iwanek@smasung.com) + */ +#include "widget_location.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +WidgetLocation::DirectoryDeletor::DirectoryDeletor(bool isReadOnly) : + m_dirpath(Jobs::WidgetInstall::createTempPath(isReadOnly)) +{} + +WidgetLocation::DirectoryDeletor::DirectoryDeletor(std::string tempPath) : + m_dirpath(tempPath) +{} + +WidgetLocation::DirectoryDeletor::~DirectoryDeletor() +{ + _D("Removing widget installation temporary directory: %s", m_dirpath.c_str()); + if (!WrtUtilRemove(m_dirpath)) { + _W("Fail at removing directory: %s", m_dirpath.c_str()); + } +} + +std::string WidgetLocation::DirectoryDeletor::getTempPath() const +{ + return m_dirpath; +} + +WidgetLocation::WidgetLocation() +{} + +WidgetLocation::WidgetLocation(const std::string & widgetname) : + m_pkgid(widgetname) +{} + +WidgetLocation::~WidgetLocation() +{} + +WidgetLocation::WidgetLocation(const std::string & widgetname, + std::string sourcePath, + WrtDB::PackagingType t, + bool isReadonly, + InstallMode::ExtensionType eType) : + m_pkgid(widgetname), + m_widgetSource(sourcePath), + m_type(t), + m_temp( + new WidgetLocation::DirectoryDeletor(isReadonly)), + m_extensionType(eType) +{ + if (isReadonly) { + m_installedPath += WrtDB::GlobalConfig::GetUserPreloadedWidgetPath(); + } else { + m_installedPath += WrtDB::GlobalConfig::GetUserInstalledWidgetPath(); + } + if (access(m_widgetSource.c_str(), F_OK) != 0) { + m_widgetSource = m_installedPath + "/" + m_pkgid; + } +} + +WidgetLocation::WidgetLocation(const std::string & widgetname, + std::string sourcePath, + std::string dirPath, + WrtDB::PackagingType t, + bool isReadonly, + InstallMode::ExtensionType eType) : + m_pkgid(widgetname), + m_widgetSource(sourcePath), + m_type(t), + m_temp(new WidgetLocation::DirectoryDeletor(dirPath)), + m_extensionType(eType) +{ + if (isReadonly) { + m_installedPath += WrtDB::GlobalConfig::GetUserPreloadedWidgetPath(); + } else { + m_installedPath += WrtDB::GlobalConfig::GetUserInstalledWidgetPath(); + } + if (access(m_widgetSource.c_str(), F_OK) != 0) { + m_widgetSource = m_installedPath + "/" + m_pkgid; + } +} + +// TODO cache all these paths +std::string WidgetLocation::getInstallationDir() const +{ + return m_installedPath; +} + +std::string WidgetLocation::getPackageInstallationDir() const +{ + return m_installedPath + "/" + m_pkgid; +} + +std::string WidgetLocation::getSourceDir() const +{ + return m_installedPath + "/" + + m_pkgid + WrtDB::GlobalConfig::GetWidgetSrcPath(); +} + +std::string WidgetLocation::getBinaryDir() const +{ + return m_installedPath + "/" + + m_pkgid + WrtDB::GlobalConfig::GetUserWidgetExecPath(); +} + +std::string WidgetLocation::getUserBinaryDir() const +{ + return getUserDataRootDir() + "/" + + WrtDB::GlobalConfig::GetUserWidgetExecPath(); +} + +std::string WidgetLocation::getExecFile() const +{ + return getBinaryDir() + "/" + m_appid; +} + +std::string WidgetLocation::getBackupDir() const +{ + return getPackageInstallationDir() + ".backup"; +} + +std::string WidgetLocation::getBackupSourceDir() const +{ + return getBackupDir() + WrtDB::GlobalConfig::GetWidgetSrcPath(); +} + +std::string WidgetLocation::getBackupBinaryDir() const +{ + return getBackupDir() + WrtDB::GlobalConfig::GetUserWidgetExecPath(); +} + +std::string WidgetLocation::getBackupExecFile() const +{ + return getBackupBinaryDir() + "/" + m_appid; +} + +std::string WidgetLocation::getBackupPrivateDir() const +{ + return getBackupDir() + "/" + + WrtDB::GlobalConfig::GetWidgetPrivateStoragePath(); +} + +std::string WidgetLocation::getUserDataRootDir() const +{ + return std::string(WrtDB::GlobalConfig::GetWidgetUserDataPath()) + + "/" + m_pkgid; +} + +std::string WidgetLocation::getPrivateStorageDir() const +{ + return getUserDataRootDir() + "/" + + WrtDB::GlobalConfig::GetWidgetPrivateStoragePath(); +} + +std::string WidgetLocation::getPrivateTempStorageDir() const +{ + return getUserDataRootDir() + "/" + + WrtDB::GlobalConfig::GetWidgetPrivateTempStoragePath(); +} + + +std::string WidgetLocation::getTemporaryPackageDir() const +{ + return m_temp->getTempPath(); +} + +std::string WidgetLocation::getTemporaryRootDir() const +{ + if (m_extensionType == InstallMode::ExtensionType::DIR) { + return getWidgetSource() + WrtDB::GlobalConfig::GetWidgetSrcPath(); + } + return getSourceDir(); +} + +DPL::String WidgetLocation::getPkgId() const +{ + return DPL::FromUTF8String(m_pkgid); +} + +std::string WidgetLocation::getInstalledIconPath() const +{ + return m_iconPath; +} + +std::string WidgetLocation::getWidgetSource() const +{ + return m_widgetSource; +} + +void WidgetLocation::setIconTargetFilenameForLocale(const std::string & icon) +{ + m_iconPath = icon; +} + +void WidgetLocation::registerExternalLocation(const std::string & file) +{ + m_externals.push_back(file); +} + +WrtDB::ExternalLocationList WidgetLocation::listExternalLocations() const +{ + return m_externals; +} + +void WidgetLocation::registerAppid(const std::string & appid) +{ + m_appid = appid; +} + +std::string WidgetLocation::getSharedRootDir() const +{ + /* TODO : add wrt-commons*/ + return getUserDataRootDir() + "/shared"; +} + +std::string WidgetLocation::getSharedResourceDir() const +{ + return getSharedRootDir() + "/res"; +} + +std::string WidgetLocation::getSharedDataDir() const +{ + return getSharedRootDir() + "/data"; +} + +std::string WidgetLocation::getSharedTrustedDir() const +{ + return getSharedRootDir() + "/trusted"; +} + +std::string WidgetLocation::getBackupSharedDir() const +{ + return getBackupDir() + "/shared"; +} + +std::string WidgetLocation::getBackupSharedDataDir() const +{ + return getBackupSharedDir() + "/data"; +} + +std::string WidgetLocation::getBackupSharedTrustedDir() const +{ + return getBackupSharedDir() + "/trusted"; +} + +std::string WidgetLocation::getNPPluginsExecFile() const +{ + return getBinaryDir() + "/" + m_appid + ".npruntime"; +} + +std::string WidgetLocation::getNPPluginsDir() const +{ + return getSourceDir() + "/plugins"; +} diff --git a/src_mobile/misc/widget_location.h b/src_mobile/misc/widget_location.h new file mode 100644 index 0000000..7208170 --- /dev/null +++ b/src_mobile/misc/widget_location.h @@ -0,0 +1,219 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file widget_location.h + * @author Iwanek Tomasz (t.iwanek@smasung.com) + */ +#ifndef WRT_INSTALLER_SRC_MISC_WIDGET_LOCATION_H +#define WRT_INSTALLER_SRC_MISC_WIDGET_LOCATION_H + +#include +#include + +#include +#include +#include +#include + +/** + * @brief The WidgetLocation class + * + * Object that stores locations of several files/directories according + * to package name + * + * Current package layout (of installed package) is following: + * + * /opt/apps/[package_name] + * \_____________ /data + * \_____________ /share + * \_____________ /bin + * \_____________ /bin/[id_of_installed_package] + * \_____________ /res/wgt/ + * \___ config.xml + * \___ [widgets_archive_content] + * + * 1) Normal Widget + * Developer provides content of res/wgt directory (package contains that + * directory as root). + * + * 2) For OSP Service Hybrid App is actually a bit different: + * Root is OSP Service directory, WebApp content is located in [root]/res/wgt + * + * Temporary directory is directory when widget is placed at the begining + * of installation process. After parsing process of config.xml, destination + * directory is created. + */ +class WidgetLocation +{ + class DirectoryDeletor + { + public: + DirectoryDeletor(); + DirectoryDeletor(std::string tempPath); + DirectoryDeletor(bool isPreload); + + ~DirectoryDeletor(); + std::string getTempPath() const; + + private: + std::string m_dirpath; + }; + + public: + DECLARE_EXCEPTION_TYPE(DPL::Exception, Base) + DECLARE_EXCEPTION_TYPE(Base, NoTemporaryPath) + /** + * @brief WidgetLocation + * + * Creates useless object. Needed by DPL::Optional + */ + WidgetLocation(); + /** + * @brief WidgetLocation Builds paths for widget location during + * uninstallation + * + * Uninstallation process needs only installed package directory. + * + * @param widgetname name of widget + */ + explicit WidgetLocation(const std::string & widgetname); + /** + * @brief WidgetLocation Builds paths for widget location during + * installation + * + * @param widgetname name of widget + * @param sourcePath given source path + * @param t declaraced type of widget if type is needed + * + * In destruction removes temporary directory + */ + WidgetLocation(const std::string & widgetname, std::string sourcePath, + WrtDB::PackagingType t = WrtDB::PKG_TYPE_NOMAL_WEB_APP, + bool isReadonly = false, + InstallMode::ExtensionType eType = + InstallMode::ExtensionType::WGT); + + WidgetLocation(const std::string & widgetname, std::string sourcePath, + std::string dirPath, + WrtDB::PackagingType t = WrtDB::PKG_TYPE_NOMAL_WEB_APP, + bool isReadonly = false, + InstallMode::ExtensionType eType = + InstallMode::ExtensionType::WGT); + + ~WidgetLocation(); + + // Installed paths + std::string getInstallationDir() const; // /opt/apps or /usr/apps + std::string getPackageInstallationDir() const; // /opt/apps/[package] + std::string getSourceDir() const; // /opt/apps/[package]/res/wgt + std::string getBinaryDir() const; // /opt/apps/[package]/bin or /usr/apps/[package]/bin + std::string getUserBinaryDir() const; // /opt/apps/[package]/bin + std::string getExecFile() const; // /opt/apps/[package]/bin/[package] + std::string getBackupDir() const; // /opt/apps/[package].backup + std::string getBackupSourceDir() const; // /opt/apps/[pkg].backup/res/wgt + std::string getBackupBinaryDir() const; // /opt/apps/[pkg].backup/bin + std::string getBackupExecFile() const; // /opt/apps/[pkg].backup/bin/[pkg] + std::string getBackupPrivateDir() const; // /opt/apps/[pkg].backup/data + std::string getUserDataRootDir() const; // /opt/usr/apps/[package] + std::string getPrivateStorageDir() const; // /opt/usr/apps/[package]/data + std::string getPrivateTempStorageDir() const; // /opt/usr/apps/[package]/tmp + std::string getSharedRootDir() const; // /opt/usr/apps/[package]/shared + std::string getSharedResourceDir() const; // /opt/usr/apps/[package]/shared/res + std::string getSharedDataDir() const; // /opt/usr/apps/[package]/shared/data + std::string getSharedTrustedDir() const; // /opt/usr/apps/[package]/shared/trusted + std::string getBackupSharedDir() const; // /opt/usr/apps/[package].backup/shared + std::string getBackupSharedDataDir() const; // /opt/usr/apps/[package].backup/shared/data + std::string getBackupSharedTrustedDir() const; // /opt/usr/apps/[package].backup/shared/trusted + std::string getNPPluginsDir() const; // /opt/usr/apps/[package]/res/wgt/plugins + std::string getNPPluginsExecFile() const; // /opt/usr/apps/[package]/bin/{execfile} + + // Temporary paths + /** + * @brief getTemporaryRootDir + * @return value of root for developer's provide package (root of unpacked + * .wgt file) + */ + std::string getTemporaryPackageDir() const; + /** + * @brief getTemporaryRootDir + * + * Value of this will differs according to type of installed widget. + * + * @return value of root for content in temporary directory to be copied + * into 'res/wgt' + */ + std::string getTemporaryRootDir() const; + + //icons + /** + * @brief setIconTargetFilenameForLocale set installed ion path according to + * locale + * @param icon path of application icon + */ + void setIconTargetFilenameForLocale(const std::string &icon); + + /** + * @brief getIconTargetFilename gets icon full path + * @param languageTag language tag + * @return value of full path + */ + std::string getInstalledIconPath() const; + + /** + * @brief getWidgetSourcePath return widget's source path given to installer + * @return value of source path + */ + std::string getWidgetSource() const; + /** + * @brief pkgid Returns pkgid + * @return pkgid + */ + DPL::String getPkgId() const; + + //external files + /** + * @brief registerExternalFile Registers file for database registration + * @param file + * + * Registered file will be stored in database and removed automatically a + * + * @return + */ + void registerExternalLocation(const std::string & file); + /** + * @brief listExternalFile list all file to be registered + */ + WrtDB::ExternalLocationList listExternalLocations() const; + + /* + * @brief set appid + */ + void registerAppid(const std::string & appid); + + private: + std::string m_pkgid; //id of package + std::string m_widgetSource; // Source widget zip + // file/widget url + std::string m_appid; //id of app + std::string m_iconPath; //installed icon path + WrtDB::PackagingType m_type; + std::shared_ptr m_temp; //directory + WrtDB::ExternalLocationList m_externals; + std::string m_installedPath; + InstallMode::ExtensionType m_extensionType; +}; + +#endif // WRT_INSTALLER_SRC_MISC_WIDGET_LOCATION_H diff --git a/src_mobile/pkg-manager/CMakeLists.txt b/src_mobile/pkg-manager/CMakeLists.txt new file mode 100755 index 0000000..74fd837 --- /dev/null +++ b/src_mobile/pkg-manager/CMakeLists.txt @@ -0,0 +1,77 @@ +# +# Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +SET(BACKLIB_SRCS + backendlib.cpp + ${PROJECT_SOURCE_DIR}/src_mobile/configuration_parser/widget_parser.cpp + ${PROJECT_SOURCE_DIR}/src_mobile/configuration_parser/parser_runner.cpp + ${PROJECT_SOURCE_DIR}/src_mobile/configuration_parser/ignoring_parser.cpp + ${PROJECT_SOURCE_DIR}/src_mobile/configuration_parser/deny_all_parser.cpp + ${PROJECT_SOURCE_DIR}/src_mobile/configuration_parser/libiriwrapper.cpp + ${PROJECT_SOURCE_DIR}/src_mobile/wrt-installer/language_subtag_rst_tree.cpp +) + +PKG_CHECK_MODULES(WRT_BACKLIB_PKGS + dpl-efl + dpl-wrt-dao-ro + dpl-wrt-dao-rw + dpl-utils-efl + pkgmgr-installer + pkgmgr-types + pkgmgr + dlog + libpcrecpp + wrt-commons-i18n-dao-ro + REQUIRED) + +INCLUDE_DIRECTORIES( + ${WRT_BACKLIB_PKGS_INCLUDE_DIRS} + ${PROJECT_SOURCE_DIR}/src/configuration_parser +) + +ADD_LIBRARY(${TARGET_BACKEND_LIB} SHARED + ${BACKLIB_SRCS} +) + +TARGET_LINK_LIBRARIES(${TARGET_BACKEND_LIB} + ${WRT_BACKLIB_PKGS_LIBRARIES} +) + +SET_TARGET_PROPERTIES(${TARGET_BACKEND_LIB} PROPERTIES + LINK_FLAGS "-Wl,--as-needed -Wl,--hash-style=both" +) + +INSTALL(TARGETS ${TARGET_BACKEND_LIB} + DESTINATION etc/package-manager/backendlib + PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE +) + +#SYMLINK +set(SYMLINK_USE OFF) +set(SYMLINK_DEST "${CMAKE_INSTALL_PREFIX}/etc/package-manager") + +IF(SYMLINK_USE) + ADD_CUSTOM_COMMAND(OUTPUT ${SYMLINK_DEST}/backend/wgt + COMMAND mkdir + ARGS -p ${SYMLINK_DEST}/backend + COMMAND ln + ARGS -sf ${CMAKE_INSTALL_PREFIX}/bin/${BACKEND} ${SYMLINK_DEST}/backend/wgt + DEPENDS ${BACKEND} + ) + ADD_CUSTOM_TARGET(test_symlinks ALL + DEPENDS ${SYMLINK_DEST}/backend/wgt + ) +ENDIF(SYMLINK_USE) diff --git a/src_mobile/pkg-manager/DESCRIPTION b/src_mobile/pkg-manager/DESCRIPTION new file mode 100644 index 0000000..a9d3696 --- /dev/null +++ b/src_mobile/pkg-manager/DESCRIPTION @@ -0,0 +1 @@ +Executables for interfacing with the package manager diff --git a/src_mobile/pkg-manager/backendlib.cpp b/src_mobile/pkg-manager/backendlib.cpp new file mode 100644 index 0000000..8367714 --- /dev/null +++ b/src_mobile/pkg-manager/backendlib.cpp @@ -0,0 +1,568 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * + * + * @file backendlib.cpp + * @author Soyoung Kim (sy037.kim@samsung.com) + * @version 0.1 + * @brief This is implementation file for providing widget information + * to package manager + */ +#include "package-manager-plugin.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "root_parser.h" +#include "widget_parser.h" +#include "parser_runner.h" +#include + +using namespace WrtDB; + +#undef TRUE +#undef FALSE +#define TRUE 0 +#define FALSE -1 +#define GET_DIRECTORY_SIZE_KB(x) (x) / 1024 + +#ifdef __cplusplus +extern "C" +{ +#endif + +static void pkg_native_plugin_on_unload(); +static int pkg_plugin_app_is_installed(const char *pkg_name); +static int pkg_plugin_get_installed_apps_list(const char *category, + const char *option, + package_manager_pkg_info_t **list, + int *count); +static int pkg_plugin_get_app_detail_info( + const char *pkg_name, + package_manager_pkg_detail_info_t * + pkg_detail_info); +static int pkg_plugin_get_app_detail_info_from_package( + const char *pkg_path, + package_manager_pkg_detail_info_t + *pkg_detail_info); + +pkgmgr_info *pkgmgr_client_check_pkginfo_from_file(const char *pkg_path); + +static void pkg_native_plugin_on_unload() +{ + _D("pkg_native_plugin_unload() is called"); +} + +static int pkg_plugin_app_is_installed(const char *pkg_name) +{ + const char* REG_PKGID_PATTERN = "^[a-zA-Z0-9]{10}$"; + _D("pkg_plugin_app_is_installed() is called"); + + WrtDB::WrtDatabase::attachToThreadRO(); + + regex_t reg; + if (regcomp(®, REG_PKGID_PATTERN, REG_NOSUB | REG_EXTENDED) != 0) { + _D("Regcomp failed"); + } + + WrtDB::TizenAppId appid; + + if (!(regexec(®, pkg_name, + static_cast(0), NULL, 0) == 0)) + { + _E("Invalid argument : %s", pkg_name); + return FALSE; + } + + Try { + WrtDB::TizenPkgId pkgid(DPL::FromUTF8String(pkg_name)); + appid = WidgetDAOReadOnly::getTzAppId(pkgid); + _D("appid : %ls", appid.c_str()); + } Catch(WidgetDAOReadOnly::Exception::WidgetNotExist) { + WrtDB::WrtDatabase::detachFromThread(); + return FALSE; + } + WrtDB::WrtDatabase::detachFromThread(); + return TRUE; +} + +static int pkg_plugin_get_installed_apps_list(const char * /*category*/, + const char * /*option*/, + package_manager_pkg_info_t **list, + int *count) +{ + _D("pkg_plugin_get_installed_apps_list() is called"); + + package_manager_pkg_info_t *pkg_list = NULL; + package_manager_pkg_info_t *pkg_last = NULL; + + WrtDB::WrtDatabase::attachToThreadRO(); + TizenAppIdList tizenAppidList = WidgetDAOReadOnly::getTizenAppidList(); + *count = 0; + + FOREACH(iterator, tizenAppidList) { + package_manager_pkg_info_t *pkg_info = + static_cast + (malloc(sizeof(package_manager_pkg_info_t))); + + if (NULL == pkg_list) { + pkg_list = pkg_info; + pkg_last = pkg_info; + } else { + pkg_last->next = pkg_info; + } + + TizenAppId tzAppid = *iterator; + WidgetDAOReadOnly widget(tzAppid); + strncpy(pkg_info->pkg_type, "wgt", PKG_TYPE_STRING_LEN_MAX); + snprintf(pkg_info->pkg_name, PKG_NAME_STRING_LEN_MAX, "%s", + DPL::ToUTF8String(tzAppid).c_str()); + + DPL::Optional version = widget.getVersion(); + if (!version.IsNull()) { + strncpy(pkg_info->version, + DPL::ToUTF8String(*version).c_str(), + PKG_VERSION_STRING_LEN_MAX - 1); + } + + (*count)++; + pkg_last = pkg_info; + } + *list = pkg_list; + WrtDB::WrtDatabase::detachFromThread(); + + return TRUE; +} + +static int pkg_plugin_get_app_detail_info( + const char *pkg_name, + package_manager_pkg_detail_info_t * + pkg_detail_info) +{ + _D("pkg_plugin_get_app_detail_info() is called"); + + WrtDB::WrtDatabase::attachToThreadRO(); + + WrtDB::TizenAppId appid; + Try { + WrtDB::TizenPkgId pkgid(DPL::FromUTF8String(pkg_name)); + appid = WidgetDAOReadOnly::getTzAppId(pkgid); + _D("appid : %ls", appid.c_str()); + } Catch(WidgetDAOReadOnly::Exception::WidgetNotExist) { + WrtDB::WrtDatabase::detachFromThread(); + return FALSE; + } + + WidgetDAOReadOnly widget(appid); + + DPL::Optional version = widget.getVersion(); + DPL::Optional id = widget.getGUID(); + DPL::Optional locale = widget.getDefaultlocale(); + + if (!version.IsNull()) { + strncpy(pkg_detail_info->version, + DPL::ToUTF8String(*version).c_str(), + PKG_VERSION_STRING_LEN_MAX - 1); + } + snprintf(pkg_detail_info->pkgid, PKG_NAME_STRING_LEN_MAX, "%s", + pkg_name); + snprintf(pkg_detail_info->optional_id, PKG_NAME_STRING_LEN_MAX, "%s", + DPL::ToUTF8String(appid).c_str()); + WidgetLocalizedInfo localizedInfo; + + if (locale.IsNull()) { + _D("locale is NULL"); + DPL::String languageTag(L""); + localizedInfo = widget.getLocalizedInfo(languageTag); + } else { + localizedInfo = widget.getLocalizedInfo(*locale); + } + DPL::Optional desc(localizedInfo.description); + + if (!desc.IsNull()) { + strncpy(pkg_detail_info->pkg_description, + DPL::ToUTF8String(*desc).c_str(), + PKG_VALUE_STRING_LEN_MAX - 1); + } + strncpy(pkg_detail_info->pkg_type, "wgt", PKG_TYPE_STRING_LEN_MAX); + strncpy(pkg_detail_info->pkg_name, pkg_name, PKG_NAME_STRING_LEN_MAX - 1); + + std::string min_version = DPL::ToUTF8String((*widget.getMinimumWacVersion())); + + strncpy(pkg_detail_info->min_platform_version, min_version.c_str(), + PKG_VERSION_STRING_LEN_MAX - 1); + + /* set installed time */ + pkg_detail_info->installed_time = widget.getInstallTime(); + + /* set Widget size */ + DPL::String pkgName = DPL::FromUTF8String(pkg_name); + std::string installPath = WidgetConfig::GetWidgetBasePath(pkgName); + std::string persistentPath = + WidgetConfig::GetWidgetPersistentStoragePath(pkgName); + std::string tempPath = + WidgetConfig::GetWidgetTemporaryStoragePath(pkgName); + installPath += "/"; + tempPath += "/"; + persistentPath += "/"; + + size_t installedSize = Utils::getFolderSize(installPath); + size_t persistentSize = Utils::getFolderSize(persistentPath); + size_t appSize = installedSize - persistentSize; + size_t dataSize = persistentSize + Utils::getFolderSize(tempPath); + + pkg_detail_info->installed_size = GET_DIRECTORY_SIZE_KB(installedSize); + pkg_detail_info->app_size = GET_DIRECTORY_SIZE_KB(appSize); + pkg_detail_info->data_size = GET_DIRECTORY_SIZE_KB(dataSize); + + WrtDB::WrtDatabase::detachFromThread(); + return TRUE; +} + +int getConfigParserData(const std::string &widgetPath, ConfigParserData& configInfo) +{ + const char* CONFIG_XML = "config.xml"; + const char* WITH_OSP_XML = "res/wgt/config.xml"; + + Try { + ParserRunner parser; + + std::unique_ptr zipFile( + new DPL::ZipInput(widgetPath)); + + std::unique_ptr configFile; + + // Open config.xml file + Try { + configFile.reset(zipFile->OpenFile(CONFIG_XML)); + } + Catch(DPL::ZipInput::Exception::OpenFileFailed) + { + configFile.reset(zipFile->OpenFile(WITH_OSP_XML)); + } + + // Extract config + DPL::BinaryQueue buffer; + DPL::AbstractWaitableInputAdapter inputAdapter(configFile.get()); + DPL::AbstractWaitableOutputAdapter outputAdapter(&buffer); + DPL::Copy(&inputAdapter, &outputAdapter); + parser.Parse(&buffer, + ElementParserPtr( + new RootParser(configInfo, + DPL:: + FromUTF32String( + L"widget")))); + } + Catch(DPL::ZipInput::Exception::OpenFailed) + { + _E("Failed to open widget package"); + return FALSE; + } + Catch(DPL::ZipInput::Exception::OpenFileFailed) + { + _E("Failed to open config.xml file"); + return FALSE; + } + Catch(DPL::CopyFailed) + { + _E("Failed to extract config.xml file"); + return FALSE; + } + Catch(DPL::FileInput::Exception::OpenFailed) + { + _E("Failed to open config.xml file"); + return FALSE; + } + Catch(ElementParser::Exception::ParseError) + { + _E("Failed to parse config.xml file"); + return FALSE; + } + Catch(DPL::ZipInput::Exception::SeekFileFailed) + { + _E("Failed to seek widget archive - corrupted package?"); + return FALSE; + } + + return TRUE; +} + +char* getIconInfo(const std::string &widgetPath, + const std::string &icon_name, int &icon_size) +{ + Try { + std::unique_ptr zipFile( + new DPL::ZipInput(widgetPath)); + + std::unique_ptr iconFile; + + Try { + iconFile.reset(zipFile->OpenFile(icon_name)); + } + Catch(DPL::ZipInput::Exception::OpenFileFailed) + { + _D("This web app is hybrid web app"); + std::string hybrid_icon = "res/wgt/" + icon_name; + iconFile.reset(zipFile->OpenFile(hybrid_icon)); + } + + DPL::BinaryQueue buffer; + DPL::AbstractWaitableInputAdapter inputAdapter(iconFile.get()); + DPL::AbstractWaitableOutputAdapter outputAdapter(&buffer); + DPL::Copy(&inputAdapter, &outputAdapter); + icon_size = buffer.Size(); + char *getBuffer = (char*) calloc(1, (sizeof(char) * icon_size) + 1); + buffer.Flatten(getBuffer, buffer.Size()); + return getBuffer; + } + Catch(DPL::ZipInput::Exception::OpenFailed) + { + _D("Failed to open widget package"); + return NULL; + } + Catch(DPL::ZipInput::Exception::OpenFileFailed) + { + _D("Not found icon file %s", icon_name.c_str()); + return NULL; + } +} + +char* getIconForLocale(const std::string& bp, const std::string& tag, + const std::string& icon, int & size) +{ + std::string iconPath; + if (!tag.empty()) { + iconPath += std::string("locales/") + tag; + } + if (!iconPath.empty()) { + iconPath += "/"; + } + + iconPath += icon; + return getIconInfo(bp, iconPath, size); +} + +char* getIcon(const std::string & basepath, const WrtDB::ConfigParserData & config, int & size) +{ + const std::list defaultIcons{ "icon.svg", "icon.ico", "icon.png", "icon.gif", "icon.jpg" }; + LanguageTags tagsList = + LanguageTagsProviderSingleton::Instance().getLanguageTags(); + + char * result = NULL; + + //for each locale tag - searching for icon presence and returning raw data + //first found is best as locale tags are ordered + FOREACH(tag, tagsList) + { + FOREACH(icon, config.iconsList) + { + std::string src = DPL::ToUTF8String(icon->src); + result = getIconForLocale(basepath, DPL::ToUTF8String(*tag), src, size); + if(result) { + return result; + } + } + FOREACH(i, defaultIcons) + { + result = getIconForLocale(basepath, DPL::ToUTF8String(*tag), *i, size); + if(result) { + return result; + } + } + } + return NULL; +} + +int getWidgetDetailInfoFromPackage(const char* pkgPath, + package_manager_pkg_detail_info_t* pkg_detail_info) +{ + const std::string widget_path(pkgPath); + ConfigParserData configInfo; + + if (FALSE == getConfigParserData(widget_path, configInfo)) { + return FALSE; + } + + strncpy(pkg_detail_info->pkg_type, "wgt", PKG_TYPE_STRING_LEN_MAX); + if (!configInfo.tizenPkgId.IsNull()) { + strncpy(pkg_detail_info->pkgid, + DPL::ToUTF8String(*configInfo.tizenPkgId).c_str(), PKG_TYPE_STRING_LEN_MAX - 1); + } + if (!configInfo.tizenAppId.IsNull()) { + strncpy(pkg_detail_info->pkg_name, + DPL::ToUTF8String(*configInfo.tizenAppId).c_str(), + PKG_NAME_STRING_LEN_MAX - 1); + } + if (!configInfo.version.IsNull()) { + strncpy(pkg_detail_info->version, + DPL::ToUTF8String(*configInfo.version).c_str(), + PKG_VERSION_STRING_LEN_MAX - 1); + } + + DPL::Optional name; + DPL::Optional desc; + + LanguageTags tags = LanguageTagsProviderSingleton::Instance().getLanguageTags(); + + auto toLowerCase = [](const DPL::String & r) + { + DPL::String result; + std::transform(r.begin(), r.end(), std::inserter(result, result.begin()), ::tolower); + return result; + }; + + if (!!configInfo.defaultlocale) + { + Locale & dl = *configInfo.defaultlocale; + configInfo.defaultlocale = toLowerCase(dl); + } + + bool found = false; + FOREACH(tag, tags) + { + *tag = toLowerCase(*tag); + FOREACH(localizedData, configInfo.localizedDataSet) + { + Locale i = localizedData->first; + i = toLowerCase(i); + + if (!!configInfo.defaultlocale && *configInfo.defaultlocale == i) + { + name = localizedData->second.name; + desc = localizedData->second.description; + } + if (*tag == i) + { + name = localizedData->second.name; + desc = localizedData->second.description; + found = true; + break; + } + } + if(found) break; + } + + if( !name.IsNull()) { + strncpy(pkg_detail_info->label, DPL::ToUTF8String(*name).c_str(), + PKG_LABEL_STRING_LEN_MAX - 1); + } + + if (!desc.IsNull()) { + strncpy(pkg_detail_info->pkg_description, + DPL::ToUTF8String(*desc).c_str(), + PKG_VALUE_STRING_LEN_MAX - 1); + } + + if (!configInfo.tizenMinVersionRequired.IsNull()) { + strncpy(pkg_detail_info->min_platform_version, + DPL::ToUTF8String(*configInfo.tizenMinVersionRequired).c_str(), + PKG_VERSION_STRING_LEN_MAX - 1); + } + + if (!configInfo.authorName.IsNull()) { + strncpy(pkg_detail_info->author, + DPL::ToUTF8String(*configInfo.authorName).c_str(), + PKG_VALUE_STRING_LEN_MAX - 1); + } + + + pkg_detail_info->privilege_list = NULL; + FOREACH(it, configInfo.featuresList) { + std::string featureInfo = DPL::ToUTF8String(it->name); + _D("privilege : %s", featureInfo.c_str()); + int length = featureInfo.size(); + char *privilege = (char*) calloc(1, (sizeof(char) * (length + 1))); + snprintf(privilege, length + 1, "%s", featureInfo.c_str()); + pkg_detail_info->privilege_list = + g_list_append(pkg_detail_info->privilege_list, privilege); + } + + char* icon_buf = getIcon(widget_path, configInfo, pkg_detail_info->icon_size); + + if (icon_buf) { + _D("icon size : %d", pkg_detail_info->icon_size); + pkg_detail_info->icon_buf = icon_buf; + } else { + _D("No icon"); + pkg_detail_info->icon_size = 0; + pkg_detail_info->icon_buf = NULL; + } + + return TRUE; +} + +static int pkg_plugin_get_app_detail_info_from_package( + const char * pkg_path, + package_manager_pkg_detail_info_t * pkg_detail_info) +{ + _D("pkg_plugin_get_app_detail_info_from_package() is called"); + return getWidgetDetailInfoFromPackage(pkg_path, pkg_detail_info); +} + +pkgmgr_info *pkgmgr_client_check_pkginfo_from_file(const char *pkg_path) +{ + _D("pkgmgr_client_check_pkginfo_from_file() is called"); + package_manager_pkg_detail_info_t *pkg_detail_info; + pkg_detail_info = (package_manager_pkg_detail_info_t*)malloc( + sizeof(package_manager_pkg_detail_info_t)); + int ret = getWidgetDetailInfoFromPackage(pkg_path, pkg_detail_info); + if (FALSE == ret) { + _E("Failed to get package detail info "); + return NULL; + } + return reinterpret_cast(pkg_detail_info); +} + +__attribute__ ((visibility("default"))) +int pkg_plugin_on_load(pkg_plugin_set *set) +{ + DPL::Log::LogSystemSingleton::Instance().SetTag("WGT-BACKLIB"); + if (NULL == set) { + return FALSE; + } + memset(set, 0x00, sizeof(pkg_plugin_set)); + + set->plugin_on_unload = pkg_native_plugin_on_unload; + set->pkg_is_installed = pkg_plugin_app_is_installed; + set->get_installed_pkg_list = pkg_plugin_get_installed_apps_list; + set->get_pkg_detail_info = pkg_plugin_get_app_detail_info; + set->get_pkg_detail_info_from_package = + pkg_plugin_get_app_detail_info_from_package; + + return TRUE; +} + +#ifdef __cplusplus +} +#endif diff --git a/src_mobile/pkg-manager/pkgmgr_signal.cpp b/src_mobile/pkg-manager/pkgmgr_signal.cpp new file mode 100644 index 0000000..140e224 --- /dev/null +++ b/src_mobile/pkg-manager/pkgmgr_signal.cpp @@ -0,0 +1,263 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @author Yunchan Cho (yunchan.cho@samsung.com) + * @version 0.1 + * @brief + */ + +#include + +#include +#include +#include + +namespace { +// package type sent in every signal +const char PKGMGR_WEBAPP_TYPE[] = "wgt"; + +// notification about opoeration start +const char PKGMGR_START_KEY[] = "start"; + +// value for new installation +const char PKGMGR_START_INSTALL[] = "install"; + +// value for update installation +const char PKGMGR_START_UPDATE[] = "update"; + +// value for uninstallation +const char PKGMGR_START_UNINSTALL[] = "uninstall"; + +// notification about progress of installation with percentage number +const char PKGMGR_PROGRESS_KEY[] = "install_percent"; + +// notification about icon path for installation frontend +const char PKGMGR_ICON_PATH[] = "icon_path"; + +// notification about error before end with given error code +// (currently, same as backend exit status) +const char PKGMGR_ERROR[] = "error"; + +// notification about end of installation with status +const char PKGMGR_END_KEY[] = "end"; + +// success value of end of installation +const char PKGMGR_END_SUCCESS[] = "ok"; + +// failure value of end of installation +const char PKGMGR_END_FAILURE[] = "fail"; +} + +namespace PackageManager { +PkgmgrSignal::PkgmgrSignal() : + m_initialized(false), + m_handle(NULL), + m_reqType(RequestType::UNSUPPORTED) +{} + +PkgmgrSignal::~PkgmgrSignal() +{} + +bool PkgmgrSignal::initialize(int argc, char* argv[]) +{ + if (m_handle) { + _D("Release already allocated pkgmgr handle"); + pkgmgr_installer_free(m_handle); + m_handle = NULL; + } + + m_handle = pkgmgr_installer_new(); + if (!m_handle) { + _E("Fail to get pkgmgr installer handle"); + return false; + } + + // set information from pkgmgr + if (!pkgmgr_installer_receive_request( + m_handle, argc, argv)) + { + auto pkgmgrtype = pkgmgr_installer_get_request_type(m_handle); + switch(pkgmgrtype) + { + case PKGMGR_REQ_INSTALL: + m_reqType = RequestType::INSTALL; + break; + case PKGMGR_REQ_UNINSTALL: + m_reqType = RequestType::UNINSTALL; + break; + case PKGMGR_REQ_REINSTALL: + m_reqType = RequestType::REINSTALL; + break; + default: + m_reqType = RequestType::UNSUPPORTED; + break; + } + + if (m_reqType == RequestType::UNSUPPORTED) + { + _E("Fail to get request type of pkgmgr"); + pkgmgr_installer_free(m_handle); + m_handle = NULL; + return false; + } + const char *callerId = pkgmgr_installer_get_caller_pkgid(m_handle); + if(callerId) + m_callerId = callerId; + + } else { + _E("Fail to get information of pkgmgr's request"); + pkgmgr_installer_free(m_handle); + m_handle = NULL; + return false; + } + + m_type = PKGMGR_WEBAPP_TYPE; + m_initialized = true; + return true; +} + +bool PkgmgrSignal::deinitialize() +{ + if (!m_initialized) { + _E("PkgmgrSingal not yet intialized"); + return false; + } + + pkgmgr_installer_free(m_handle); + m_handle = NULL; + m_initialized = false; + return true; +} + +bool PkgmgrSignal::setPkgname(const std::string& name) +{ + if (!m_initialized) { + _E("PkgmgrSingal not yet intialized"); + return false; + } + + if (name.empty()) { + _E("name is empty"); + return false; + } + + m_pkgname = name; + _D("Success to set tizen package name: %s", m_pkgname.c_str()); + + return true; +} + +bool PkgmgrSignal::startJob(Jobs::InstallationType type) +{ + switch(type) + { + case Jobs::InstallationType::NewInstallation: + sendSignal(PKGMGR_START_KEY, PKGMGR_START_INSTALL); + break; + case Jobs::InstallationType::UpdateInstallation: + sendSignal(PKGMGR_START_KEY, PKGMGR_START_UPDATE); + break; + case Jobs::InstallationType::Uninstallation: + sendSignal(PKGMGR_START_KEY, PKGMGR_START_UNINSTALL); + break; + default: + _E("Trying to send unknown installation type to pkgmgr"); + return false; + } + return true; +} + +bool PkgmgrSignal::endJob(Jobs::Exceptions::Type ecode) +{ + if(ecode == Jobs::Exceptions::Type::Success) + { + return sendSignal(PKGMGR_END_KEY, PKGMGR_END_SUCCESS); + } + else + { + sendSignal(PKGMGR_ERROR, DPL::lexical_cast(ecode)); + return sendSignal(PKGMGR_END_KEY, PKGMGR_END_FAILURE); + } +} + +bool PkgmgrSignal::sendProgress(int percent) +{ + return sendSignal(PKGMGR_PROGRESS_KEY, DPL::lexical_cast(percent)); +} + +bool PkgmgrSignal::sendIconPath(const std::string & iconpath) +{ + return sendSignal(PKGMGR_ICON_PATH, iconpath); +} + +bool PkgmgrSignal::sendSignal(const std::string& key, + const std::string& value) const +{ + if (!m_initialized) { + _E("PkgmgrSingal not yet intialized"); + return false; + } + + if (key.empty() || value.empty()) { + _D("key or value is empty"); + return false; + } + + if (m_handle == NULL || m_type.empty()) { + _E("Some data of PkgmgrSignal is empty"); + return false; + } + + // send pkgmgr signal + if (pkgmgr_installer_send_signal( + m_handle, m_type.c_str(), m_pkgname.c_str(), + key.c_str(), value.c_str())) + { + _E("Fail to send pkgmgr signal"); + return false; + } + + _D("Success to send pkgmgr signal: %s - %s", key.c_str(), value.c_str()); + return true; +} + +std::string PkgmgrSignal::getPkgname() const +{ + if (!m_initialized) { + _E("PkgmgrSingal not yet intialized"); + } + + return m_pkgname; +} + +PkgmgrSignal::RequestType PkgmgrSignal::getRequestedType() const +{ + if (!m_initialized) { + _E("PkgmgrSingal not yet intialized"); + } + + return m_reqType; +} + +std::string PkgmgrSignal::getCallerId() const +{ + if (!m_initialized) { + _E("PkgmgrSingal not yet intialized"); + } + + return m_callerId; +} +} // PackageManager diff --git a/src_mobile/pkg-manager/pkgmgr_signal.h b/src_mobile/pkg-manager/pkgmgr_signal.h new file mode 100644 index 0000000..abd756b --- /dev/null +++ b/src_mobile/pkg-manager/pkgmgr_signal.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @author Yunchan Cho (yunchan.cho@samsung.com) + * @author Jan Olszak (j.olszak@samsung.com) + * @version 0.2 + * @brief + */ + +#ifndef WRT_PKGMGR_SIGNAL_H_ +#define WRT_PKGMGR_SIGNAL_H_ + +#include + +struct pkgmgr_installer; + +namespace PackageManager { + +class PkgmgrSignal : public IPkgmgrSignal +{ +public: + enum class RequestType + { + UNSUPPORTED, + INSTALL, + UNINSTALL, + REINSTALL + }; + + bool initialize(int argc, char* argv[]); + bool deinitialize(); + bool setPkgname(const std::string& name); + std::string getPkgname() const; + RequestType getRequestedType() const; + std::string getCallerId() const; + + bool startJob(Jobs::InstallationType type); + bool endJob(Jobs::Exceptions::Type ecode); + bool sendProgress(int percent); + bool sendIconPath(const std::string & iconpath); + + PkgmgrSignal(); + virtual ~PkgmgrSignal(); + +protected: + bool sendSignal(const std::string& key, const std::string& value) const; + +private: + bool m_initialized; + pkgmgr_installer* m_handle; + std::string m_type; + std::string m_pkgname; + RequestType m_reqType; + std::string m_callerId; +}; +} // PackageManager + +#endif // WRT_PKGMGR_SIGNAL_H_ + diff --git a/src_mobile/pkg-manager/pkgmgr_signal_dummy.h b/src_mobile/pkg-manager/pkgmgr_signal_dummy.h new file mode 100644 index 0000000..42b0aa4 --- /dev/null +++ b/src_mobile/pkg-manager/pkgmgr_signal_dummy.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @author Jan Olszak (j.olszak@samsung.com) + * @version 0.1 + * @brief Dummy version of PkgmgrSignal. + */ + +#ifndef WRT_PKGMGR_SIGNAL_DUMMY_H_ +#define WRT_PKGMGR_SIGNAL_DUMMY_H_ + +#include + +#include + +namespace PackageManager { +class PkgmgrSignalDummy : public IPkgmgrSignal +{ + public: + PkgmgrSignalDummy() + {} + + virtual ~PkgmgrSignalDummy() + {} + + bool setPkgname(const std::string& /*name*/) + { + return false; + } + + std::string getPkgname() const + { + return ""; + } + + std::string getCallerId() const + { + return ""; + } + + bool startJob(Jobs::InstallationType type DPL_UNUSED) + { + return false; + } + + bool endJob(Jobs::Exceptions::Type ecode DPL_UNUSED) + { + return false; + } + + bool sendProgress(int percent DPL_UNUSED) + { + return false; + } + + bool sendIconPath(const std::string & iconpath DPL_UNUSED) + { + return false; + } +}; +} // PkgmgrSignalDummy + +#endif // WRT_PKGMGR_SIGNAL_DUMMY_H_ diff --git a/src_mobile/pkg-manager/pkgmgr_signal_interface.h b/src_mobile/pkg-manager/pkgmgr_signal_interface.h new file mode 100644 index 0000000..1e38a17 --- /dev/null +++ b/src_mobile/pkg-manager/pkgmgr_signal_interface.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @author Jan Olszak (j.olszak@samsung.com) + * @version 0.1 + * @brief Interface for PkgmgrSignal. + */ + +#ifndef WRT_PKGMGR_SIGNAL_INTERFACE_H_ +#define WRT_PKGMGR_SIGNAL_INTERFACE_H_ + +#include + +#include +#include + +namespace PackageManager { +class IPkgmgrSignal +{ + public: + virtual bool setPkgname(const std::string& name) = 0; + virtual std::string getPkgname() const = 0; + virtual std::string getCallerId() const = 0; + + virtual bool startJob(Jobs::InstallationType type) = 0; + virtual bool endJob(Jobs::Exceptions::Type ecode) = 0; + virtual bool sendProgress(int percent) = 0; + virtual bool sendIconPath(const std::string & iconpath) = 0; + virtual ~IPkgmgrSignal(){} +}; +} // IPkgmgrSignal + +#endif // WRT_PKGMGR_SIGNAL_INTERFACE_H_ diff --git a/src_mobile/wrt-installer/CMakeLists.txt b/src_mobile/wrt-installer/CMakeLists.txt new file mode 100644 index 0000000..e22fdc5 --- /dev/null +++ b/src_mobile/wrt-installer/CMakeLists.txt @@ -0,0 +1,75 @@ +# Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# @file CMakeLists.txt +# @author Lukasz Wrzosek (l.wrzosek@samsung.com) +# @version 1.0 +# + +SET(WRT_INSTALLER_DIR + ${INSTALLER_SRC_DIR}/wrt-installer + ) + +SET(PKG_MANAGER_DIR + ${INSTALLER_SRC_DIR}/pkg-manager + ) + +SET(WRT_INSTALLER_SOURCES + ${WRT_INSTALLER_DIR}/wrt-installer.cpp + ${WRT_INSTALLER_DIR}/wrt_installer_api.cpp + ${WRT_INSTALLER_DIR}/installer_callbacks_translate.cpp + ${WRT_INSTALLER_DIR}/plugin_utils.cpp + ${WRT_INSTALLER_DIR}/language_subtag_rst_tree.cpp + ${WRT_INSTALLER_DIR}/installer_main_thread.cpp + ${WRT_INSTALLER_DIR}/option_parser.cpp + ${PKG_MANAGER_DIR}/pkgmgr_signal.cpp +) + +PKG_CHECK_MODULES(WRT_INSTALLER_DEPS + pkgmgr-installer + libpcrecpp + pkgmgr-info + pkgmgr + security-install + wrt-commons-i18n-dao-ro + REQUIRED) + +INCLUDE_DIRECTORIES( + ${PKG_MANAGER_DIR} + ${WRT_INSTALLER_DEP_INCLUDES} + ${WRT_INSTALLER_INCLUDES} + ${WRT_INSTALLER_DEPS_INCLUDE_DIRS} +) + +ADD_EXECUTABLE(${TARGET_INSTALLER} + ${TARGET_INSTALLER_STATIC_SRC} + ${WRT_INSTALLER_SOURCES} +) + +ADD_DEFINITIONS(${WRT_INSTALLER_DEPS_CFLAGS}) + +TARGET_LINK_LIBRARIES(${TARGET_INSTALLER} + ${TARGET_INSTALLER_STATIC} + ${WRT_INSTALLER_DEPS_LIBRARIES} +) + + +SET_TARGET_PROPERTIES(${TARGET_INSTALLER} PROPERTIES + LINK_FLAGS "-Wl,--as-needed -Wl,--hash-style=both" + BUILD_WITH_INSTALL_RPATH ON + INSTALL_RPATH_USE_LINK_PATH ON +) + +INSTALL(TARGETS ${TARGET_INSTALLER} DESTINATION bin) diff --git a/src_mobile/wrt-installer/installer_callbacks_translate.cpp b/src_mobile/wrt-installer/installer_callbacks_translate.cpp new file mode 100644 index 0000000..ca52dd6 --- /dev/null +++ b/src_mobile/wrt-installer/installer_callbacks_translate.cpp @@ -0,0 +1,262 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file api_callbacks_translate.h + * @author Pawel Sikorski (p.sikorski@samsung.com) + * @version 1.0 + * @brief Source file for api callbacks translate functions + */ + +#include +#include +#include + +namespace InstallerCallbacksTranslate { + +// callback for finished install +void installFinishedCallback(void *userParam, + std::string tizenId, + Jobs::Exceptions::Type status) +{ + Assert(userParam != NULL); + + StatusCallbackStruct *apiStr = + static_cast(userParam); + + if (apiStr->status_callback) { + // Translate error + WrtErrStatus errorStatus; + + switch (status) { + case Jobs::Exceptions::Success: + errorStatus = WRT_SUCCESS; + break; + + case Jobs::Exceptions::ErrorPackageNotFound: + errorStatus = WRT_INSTALLER_ERROR_PACKAGE_NOT_FOUND; + break; + + case Jobs::Exceptions::ErrorPackageInvalid: + errorStatus = WRT_INSTALLER_ERROR_PACKAGE_INVALID; + break; + + case Jobs::Exceptions::ErrorPackageLowerVersion: + errorStatus = WRT_INSTALLER_ERROR_PACKAGE_LOWER_VERSION; + break; + + case Jobs::Exceptions::ErrorPackageExecutableNotFound: + errorStatus = WRT_INSTALLER_ERROR_PACKAGE_EXCUTABLE_NOT_FOUND; + break; + + case Jobs::Exceptions::ErrorManifestNotFound: + errorStatus = WRT_INSTALLER_ERROR_MANIFEST_NOT_FOUND; + break; + + case Jobs::Exceptions::ErrorManifestInvalid: + errorStatus = WRT_INSTALLER_ERROR_MANIFEST_INVALID; + break; + + case Jobs::Exceptions::ErrorConfigNotFound: + errorStatus = WRT_INSTALLER_CONFIG_NOT_FOUND; + break; + + case Jobs::Exceptions::ErrorConfigInvalid: + errorStatus = WRT_INSTALLER_ERROR_CONFIG_INVALID; + break; + + case Jobs::Exceptions::ErrorSignatureNotFound: + errorStatus = WRT_INSTALLER_ERROR_SIGNATURE_NOT_FOUND; + break; + + case Jobs::Exceptions::ErrorSignatureInvalid: + errorStatus = WRT_INSTALLER_ERROR_SIGNATURE_INVALID; + break; + + case Jobs::Exceptions::ErrorSignatureVerificationFailed: + errorStatus = WRT_INSTALLER_ERROR_SIGNATURE_VERIFICATION_FAILED; + break; + + case Jobs::Exceptions::ErrorRootCertificateNotFound: + errorStatus = WRT_INSTALLER_ERROR_ROOT_CERTIFICATE_NOT_FOUND; + break; + + case Jobs::Exceptions::ErrorCertificationInvaid: + errorStatus = WRT_INSTALLER_ERROR_CERTIFICATION_INVAID; + break; + + case + Jobs::Exceptions::ErrorCertificateChainVerificationFailed: + errorStatus = + WRT_INSTALLER_ERROR_CERTIFICATE_CHAIN_VERIFICATION_FAILED; + break; + + case Jobs::Exceptions::ErrorCertificateExpired: + errorStatus = WRT_INSTALLER_ERROR_CERTIFICATE_EXPIRED; + break; + + case Jobs::Exceptions::ErrorInvalidPrivilege: + errorStatus = WRT_INSTALLER_ERROR_INVALID_PRIVILEGE; + break; + + case Jobs::Exceptions::ErrorPrivilegeLevelViolation: + errorStatus = WRT_INSTALLER_ERROR_PRIVILEGE_LEVEL_VIOLATION; + break; + + case Jobs::Exceptions::ErrorMenuIconNotFound: + errorStatus = WRT_INSTALLER_ERROR_MENU_ICON_NOT_FOUND; + break; + + case Jobs::Exceptions::ErrorFatalError: + errorStatus = WRT_INSTALLER_ERROR_FATAL_ERROR; + break; + + case Jobs::Exceptions::ErrorOutOfStorage: + errorStatus = WRT_INSTALLER_ERROR_OUT_OF_STORAGE; + break; + + case Jobs::Exceptions::ErrorOutOfMemory: + errorStatus = WRT_INSTALLER_ERROR_OUT_OF_MEMORY; + break; + + case Jobs::Exceptions::ErrorArgumentInvalid: + errorStatus = WRT_INSTALLER_ERROR_ARGUMENT_INVALID; + break; + + case Jobs::Exceptions::ErrorPackageAlreadyInstalled: + errorStatus = WRT_INSTALLER_ERROR_PACKAGE_ALREADY_INSTALLED; + break; + + case Jobs::Exceptions::ErrorAceCheckFailed: + errorStatus = WRT_INSTALLER_ERROR_ACE_CHECK_FAILED; + break; + + case Jobs::Exceptions::ErrorManifestCreateFailed: + errorStatus = WRT_INSTALLER_ERROR_MANIFEST_CREATE_FAILED; + break; + + case Jobs::Exceptions::ErrorEncryptionFailed: + errorStatus = WRT_INSTALLER_ERROR_ENCRYPTION_FAILED; + break; + + case Jobs::Exceptions::ErrorInstallOspServcie: + errorStatus = WRT_INSTALLER_ERROR_INSTALL_OSP_SERVCIE; + break; + + default: + errorStatus = WRT_INSTALLER_ERROR_UNKNOWN; + break; + } + + // Callback + apiStr->status_callback(tizenId, errorStatus, apiStr->userdata); + } else { + _D("installFinishedCallback: No callback"); + } +} + +// callback for finished install +void uninstallFinishedCallback(void *userParam, + std::string tizenId, + Jobs::Exceptions::Type status) +{ + Assert(userParam != NULL); + + StatusCallbackStruct *apiStr = + static_cast(userParam); + + if (apiStr->status_callback) { + // Translate error + WrtErrStatus errorStatus; + + switch (status) { + case Jobs::Exceptions::Success: + errorStatus = WRT_SUCCESS; + break; + + case Jobs::Exceptions::ErrorWidgetUninstallationFailed: + errorStatus = WRT_INSTALLER_ERROR_UNINSTALLATION_FAILED; + break; + + case Jobs::Exceptions::ErrorUnknown: + errorStatus = WRT_INSTALLER_ERROR_UNKNOWN; + break; + + default: + errorStatus = WRT_INSTALLER_ERROR_UNKNOWN; + break; + } + + // Callback + apiStr->status_callback(tizenId, errorStatus, apiStr->userdata); + } else { + _D("uninstallFinishedCallback: No callback"); + } +} + +void pluginInstallFinishedCallback(void *userParam, + Jobs::Exceptions::Type status) +{ + Assert(userParam); + + PluginStatusCallbackStruct *apiStr = + static_cast(userParam); + + if (apiStr->statusCallback) { + // Translate error + WrtErrStatus errorStatus; + + switch (status) { + case Jobs::Exceptions::Success: + errorStatus = WRT_SUCCESS; + break; + case Jobs::Exceptions::ErrorPluginInstallationFailed: + errorStatus = WRT_INSTALLER_ERROR_PLUGIN_INSTALLATION_FAILED; + break; + default: + errorStatus = WRT_INSTALLER_ERROR_UNKNOWN; + break; + } + + apiStr->statusCallback(errorStatus, apiStr->userdata); + } else { + _D("PluginInstallFinishedCallback: No callback"); + } + + delete apiStr; +} + +// callback for progress of install OR uninstall +void installProgressCallback(void *userParam, + ProgressPercent percent, + const ProgressDescription &description) +{ + Assert(userParam != NULL); + + StatusCallbackStruct *apiStr = + static_cast(userParam); + + if (apiStr->progress_callback) { + //CALLBACK EXEC + _D("Entered %2.0f%% %s", percent, description.c_str()); + apiStr->progress_callback(static_cast(percent), + description.c_str(), + apiStr->userdata); + } else { + _D("installProgressCallback: ignoring NULL callback pointer"); + } +} +} //namespace + diff --git a/src_mobile/wrt-installer/installer_callbacks_translate.h b/src_mobile/wrt-installer/installer_callbacks_translate.h new file mode 100644 index 0000000..5322078 --- /dev/null +++ b/src_mobile/wrt-installer/installer_callbacks_translate.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file api_callbacks_translate.h + * @author Pawel Sikorski (p.sikorski@samsung.com) + * @version 1.0 + * @brief Header file for api callbacks translate functions + */ +#ifndef WRT_SRC_API_API_CALLBACKS_TRANSLATE_H_ +#define WRT_SRC_API_API_CALLBACKS_TRANSLATE_H_ + +#include +#include +#include +#include +#include +#include +#include + +namespace InstallerCallbacksTranslate { +struct StatusCallbackStruct +{ + void* userdata; + WrtInstallerStatusCallback status_callback; + WrtProgressCallback progress_callback; + + StatusCallbackStruct(void* u, + WrtInstallerStatusCallback s, + WrtProgressCallback p) : + userdata(u), + status_callback(s), + progress_callback(p) + {} +}; + +struct PluginStatusCallbackStruct +{ + void* userdata; + WrtPluginInstallerStatusCallback statusCallback; + WrtProgressCallback progressCallback; + + PluginStatusCallbackStruct(void* u, + WrtPluginInstallerStatusCallback s, + WrtProgressCallback p) : + userdata(u), + statusCallback(s), + progressCallback(p) + {} +}; + +void installFinishedCallback(void *userParam, + std::string tizenId, + Jobs::Exceptions::Type status); + +void uninstallFinishedCallback(void *userParam, + std::string tizenId, + Jobs::Exceptions::Type status); + +void pluginInstallFinishedCallback(void *userParam, + Jobs::Exceptions::Type status); + +// callback for progress of install OR uninstall +void installProgressCallback(void *userParam, + ProgressPercent percent, + const ProgressDescription &description); +} //namespace + +#endif /* WRT_SRC_API_API_CALLBACKS_TRANSLATE_H_ */ diff --git a/src_mobile/wrt-installer/installer_main_thread.cpp b/src_mobile/wrt-installer/installer_main_thread.cpp new file mode 100644 index 0000000..b398d3c --- /dev/null +++ b/src_mobile/wrt-installer/installer_main_thread.cpp @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file installer_main_thread.cpp + * @author Krzysztof Jackiewicz (k.jackiewicz@samsung.com) + * @version 1.0 + */ + +#include "installer_main_thread.h" +#include +#include +#include +#include +#include +#include +#include + +IMPLEMENT_SINGLETON(InstallerMainThread) + +using namespace WrtDB; + +InstallerMainThread::InstallerMainThread() : m_attached(false) {} + +InstallerMainThread::~InstallerMainThread() +{ + Assert(!m_attached); +} + +void InstallerMainThread::AttachDatabases() +{ + Assert(!m_attached); + // Attach databases + ValidationCore::AttachToThreadRW(); + ace_return_t ret = ace_install_initialize(); + Assert(ACE_OK == ret); // to be changed to exception in the future + WrtDB::WrtDatabase::attachToThreadRW(); + m_attached = true; +} + +void InstallerMainThread::DetachDatabases() +{ + Assert(m_attached); + m_attached = false; + // Detach databases + ValidationCore::DetachFromThread(); + ace_return_t ret = ace_install_shutdown(); + Assert(ACE_OK == ret); // to be changed to exception in the future + WrtDB::WrtDatabase::detachFromThread(); +} + +void InstallerMainThread::TouchArchitecture() +{ + // Touch controller + Logic::InstallerControllerSingleton::Instance().Touch(); +} + +void InstallerMainThread::TouchArchitectureOnlyInstaller() +{ + // Touch controller + Logic::InstallerControllerSingleton::Instance().Touch(); +} diff --git a/src_mobile/wrt-installer/installer_main_thread.h b/src_mobile/wrt-installer/installer_main_thread.h new file mode 100644 index 0000000..bd70b16 --- /dev/null +++ b/src_mobile/wrt-installer/installer_main_thread.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file installer_main_thread.h + * @author Krzysztof Jackiewicz (k.jackiewicz@samsung.com) + * @version 1.0 + */ + +#ifndef INSTALLER_MAINTHREAD_H_ +#define INSTALLER_MAINTHREAD_H_ + +#include + +class InstallerMainThread +{ + public: + void AttachDatabases(); + void DetachDatabases(); + void TouchArchitecture(); + void TouchArchitectureOnlyInstaller(); + + private: + friend class DPL::Singleton; + + InstallerMainThread(); + virtual ~InstallerMainThread(); + + bool m_attached; +}; + +typedef DPL::Singleton InstallerMainThreadSingleton; + +#endif /* INSTALLER_MAINTHREAD_H_ */ diff --git a/src_mobile/wrt-installer/language_subtag_rst_tree.cpp b/src_mobile/wrt-installer/language_subtag_rst_tree.cpp new file mode 100644 index 0000000..a2bfaf5 --- /dev/null +++ b/src_mobile/wrt-installer/language_subtag_rst_tree.cpp @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file language_subtag_rst_tree.cpp + * @author Lukasz Wrzosek (l.wrzosek@samsung.com) + * @version 1.0 + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +IMPLEMENT_SINGLETON(LanguageSubtagRstTree) + +namespace I18nDAOReadOnly = I18n::DB::I18nDAOReadOnly; + +bool LanguageSubtagRstTree::ValidateLanguageTag(const std::string &tag_input) +{ + std::string tag = tag_input; + std::transform(tag.begin(), tag.end(), tag.begin(), &tolower); + + std::vector parts; + DPL::Tokenize(DPL::FromUTF8String(tag), + '-', + std::back_inserter(parts), + false); + std::vector::iterator token = parts.begin(); + if (token == parts.end()) + { + return false; + } + + I18n::DB::Interface::attachDatabaseRO(); + DPL_SCOPE_EXIT() + { + I18n::DB::Interface::detachDatabase(); + }; + + if (I18nDAOReadOnly::IsValidSubTag(*token, RECORD_TYPE_LANGUAGE)) + { + ++token; + } + else + { + return false; + } + + if (token == parts.end()) + { + return true; + } + + if (I18nDAOReadOnly::IsValidSubTag(*token, RECORD_TYPE_EXTLANG)) + { + ++token; + } + + if (token == parts.end()) + { + return true; + } + + if (I18nDAOReadOnly::IsValidSubTag(*token, RECORD_TYPE_SCRIPT)) + { + ++token; + } + + if (token == parts.end()) + { + return true; + } + + if (I18nDAOReadOnly::IsValidSubTag(*token, RECORD_TYPE_REGION)) + { + ++token; + } + + if (token == parts.end()) + { + return true; + } + + while (token != parts.end()) + { + if (I18nDAOReadOnly::IsValidSubTag(*token, RECORD_TYPE_VARIANT)) + { + ++token; + } + else + { + break; + } + } + + //'u' - unicode extension - only one BCP47 extension is registered. + //TODO: unicode extension should be also validated (l.wrzosek) + if (token == parts.end()) + { + return true; + } + + if (*token == L"u") + { + ++token; + bool one_or_more = false; + while (token != parts.end() && + token->size() > 1 && + token->size() <= 8) + { + one_or_more = true; + ++token; + } + if (!one_or_more) + { + return false; + } + } + + //'x' - privateuse + if (token == parts.end()) + { + return true; + } + + if (*token == L"x") + { + ++token; + bool one_or_more = false; + while (token != parts.end() && + !token->empty() && + token->size() <= 8) + { + one_or_more = true; + ++token; + } + if (!one_or_more) + { + return false; + } + } + + if (token == parts.end()) + { + return true; + } + + //Try private use now: + token = parts.begin(); + if (*token == L"x") + { + ++token; + bool one_or_more = false; + while (token != parts.end() && + !token->empty() && + token->size() <= 8) + { + one_or_more = true; + ++token; + } + return one_or_more; + } + + //grandfathered is always rejected + return false; +} + +#define TEST_LANG(str, cond) \ + if (LanguageSubtagRstTreeSingleton::Instance(). \ + ValidateLanguageTag(str) == cond) { \ + _D("Good validate status for lang: %s", str); \ + } else { \ + _E("Wrong validate status for lang: %s, should be %d", str, cond); \ + } + +void LanguageSubtagRstTree::Initialize() +{ + /* Temporarily added unit test. Commented out due to performance drop. + * TEST_LANG("zh", true); + * TEST_LANG("esx-al", true); + * TEST_LANG("zh-Hant", true); + * TEST_LANG("zh-Hant-CN", true); + * TEST_LANG("zh-Hant-CN-x-private1-private2", true); + * TEST_LANG("plxxx", false); + * TEST_LANG("pl-x-private111", false); + * TEST_LANG("x-private1", false); //do not support pure private ones + * TEST_LANG("x-private22", false); + * TEST_LANG("i-private22", false); //do not support i-* + */ +} + +#undef TEST_LANG diff --git a/src_mobile/wrt-installer/language_subtag_rst_tree.h b/src_mobile/wrt-installer/language_subtag_rst_tree.h new file mode 100644 index 0000000..b057059 --- /dev/null +++ b/src_mobile/wrt-installer/language_subtag_rst_tree.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file language_subtag_rst_tree.h + * @author Lukasz Wrzosek (l.wrzosek@samsung.com) + * @version 1.0 + */ +#ifndef LANGUAGE_SUBTAG_RST_TREE_H +#define LANGUAGE_SUBTAG_RST_TREE_H + +#include +#include +#include +class LanguageSubtagRstTree : DPL::Noncopyable +{ + public: + void Initialize(); + bool ValidateLanguageTag(const std::string &tag); +}; + +typedef DPL::Singleton LanguageSubtagRstTreeSingleton; + +enum iana_record_types_e +{ + RECORD_TYPE_LANGUAGE, + RECORD_TYPE_SCRIPT, + RECORD_TYPE_REGION, + RECORD_TYPE_VARIANT, + RECORD_TYPE_GRANDFATHERED, + RECORD_TYPE_REDUNDANT, + RECORD_TYPE_EXTLANG +}; + +#endif //LANGUAGE_SUBTAG_RST_TREE_H diff --git a/src_mobile/wrt-installer/option_parser.cpp b/src_mobile/wrt-installer/option_parser.cpp new file mode 100644 index 0000000..982d86f --- /dev/null +++ b/src_mobile/wrt-installer/option_parser.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file option_parser.cpp + * @author Zbigniew Kostrzewa (z.kostrzewa@samsung.com) + * @brief Implementation file for OptionParser. + */ + +#include +#include +#include +#include "option_parser.h" + +DPL::OptionalString OptionParser::QueryOption(int argc, + char* argv[], + const std::string& name) +{ + DPL::OptionalString result; + + std::vector args(argv, (argv + argc)); + + auto it = std::find_if(args.begin(), + args.end(), + [&name](const std::string & option){ + return (option == name); + }); + + if (it != args.end()) { + std::string value; + while ((++it != args.end()) && !IsOption(*it)) { + value += *it + " "; + } + result = DPL::FromUTF8String(value); + } + + return result; +} + +bool OptionParser::IsOption(const std::string& name) +{ + return (name.find('-') == 0); +} diff --git a/src_mobile/wrt-installer/option_parser.h b/src_mobile/wrt-installer/option_parser.h new file mode 100644 index 0000000..7fa8c3a --- /dev/null +++ b/src_mobile/wrt-installer/option_parser.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file option_parser.h + * @author Zbigniew Kostrzewa (z.kostrzewa@samsung.com) + * @brief Header file for OptionParser. + */ + +#ifndef WRT_INSTALLER_SRC_WRT_INSTALLER_OPTION_PARSER_H_ +#define WRT_INSTALLER_SRC_WRT_INSTALLER_OPTION_PARSER_H_ + +#include +#include + +class OptionParser +{ + public: + static DPL::OptionalString QueryOption(int argc, + char* argv[], + const std::string & name); + + private: + static bool IsOption(const std::string& name); +}; + +#endif diff --git a/src_mobile/wrt-installer/plugin_utils.cpp b/src_mobile/wrt-installer/plugin_utils.cpp new file mode 100644 index 0000000..cabda19 --- /dev/null +++ b/src_mobile/wrt-installer/plugin_utils.cpp @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file plugin-utils.cpp + * @author + * @version 1.0 + * @brief Header file for plugin util + */ + +#include +#include "plugin_utils.h" +#include +#include +#include +#include + +using namespace WrtDB; + +namespace PluginUtils { +const char* PLUGIN_INSTALL_LOCK_FILE = "/tmp/.wrt_plugin_install_lock"; + +static int s_plugin_install_lock_fd = -1; + +bool lockPluginInstallation(bool isPreload) +{ + if (isPreload) { + fprintf(stderr, "Skip create lock file.. \n"); + return true; + } + + int ret = 0; + + _D("Try to lock for plugins installation."); + + s_plugin_install_lock_fd = + open(PLUGIN_INSTALL_LOCK_FILE, O_RDONLY | O_CREAT, 0666); + + if (s_plugin_install_lock_fd == -1) { + _E("Lock file open failed!"); + + return false; + } + + ret = flock(s_plugin_install_lock_fd, LOCK_EX); //lock with waiting + + if (ret == -1) { + _E("Lock failed!"); + + close(s_plugin_install_lock_fd); + s_plugin_install_lock_fd = -1; + + return false; + } + + return true; +} + +bool unlockPluginInstallation(bool isPreload) +{ + _D("Unlock for plugins installation."); + if (isPreload) { + fprintf(stderr, "Skip plugin unlock.. \n"); + return true; + } + + if (s_plugin_install_lock_fd != -1) { + int ret = 0; + + ret = flock(s_plugin_install_lock_fd, LOCK_UN); //unlock + + if (ret == -1) { + _E("Unlock failed!"); + } + + close(s_plugin_install_lock_fd); + s_plugin_install_lock_fd = -1; + + return true; + } else { + _E("Lock file was not created!"); + } + + return false; +} + +bool checkPluginInstallationRequired() +{ + std::string installRequest = + std::string(GlobalConfig::GetPluginInstallInitializerName()); + + FileState::Type installationRequest = + checkFile(installRequest); + + switch (installationRequest) { + case FileState::FILE_EXISTS: + return true; + case FileState::FILE_NOT_EXISTS: + return false; + default: + _W("Opening installation request file failed"); + return false; + } +} + +bool removeInstallationRequiredFlag() +{ + std::string installRequest = + std::string(GlobalConfig::GetPluginInstallInitializerName()); + + return removeFile(installRequest); +} + +//checks if file exists and is regular file +FileState::Type checkFile(const std::string& filename) +{ + struct stat tmp; + + if (-1 == stat(filename.c_str(), &tmp)) { + if (ENOENT == errno) { + return FileState::FILE_NOT_EXISTS; + } + return FileState::FILE_READ_DATA_ERROR; + } else if (!S_ISREG(tmp.st_mode)) { + return FileState::FILE_EXISTS_NOT_REGULAR; + } + return FileState::FILE_EXISTS; +} + +bool removeFile(const std::string& filename) +{ + if (0 != unlink(filename.c_str())) { + return false; + } + + return true; +} +} //namespace PluginUtils diff --git a/src_mobile/wrt-installer/plugin_utils.h b/src_mobile/wrt-installer/plugin_utils.h new file mode 100644 index 0000000..8659f20 --- /dev/null +++ b/src_mobile/wrt-installer/plugin_utils.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file plugin-utils.h + * @author + * @version 1.0 + * @brief Header file for plugin util + */ +#ifndef PLUGIN_UTILS_H +#define PLUGIN_UTILS_H + +#include +#include + +namespace PluginUtils { +struct FileState +{ + enum Type + { + FILE_EXISTS, + FILE_EXISTS_NOT_REGULAR, + FILE_NOT_EXISTS, + FILE_READ_DATA_ERROR + }; +}; + +bool lockPluginInstallation(bool isPreload); +bool unlockPluginInstallation(bool isPreload); +bool checkPluginInstallationRequired(); +bool removeInstallationRequiredFlag(); +FileState::Type checkFile(const std::string& filename); +bool removeFile(const std::string& filename); +} +#endif // PLUGIN_UTILS_H diff --git a/src_mobile/wrt-installer/wrt-installer.cpp b/src_mobile/wrt-installer/wrt-installer.cpp new file mode 100644 index 0000000..61a0c2a --- /dev/null +++ b/src_mobile/wrt-installer/wrt-installer.cpp @@ -0,0 +1,1160 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* @file wrt-installer.cpp + * @version 1.0 + * @brief Implementation file for installer + */ + +#include "wrt-installer.h" +#include "plugin_utils.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +using namespace WrtDB; + +namespace { // anonymous +const char * const PKGMGR_INSTALL_MSG = "Install widget"; +const char * const PKGMGR_UNINSTALL_MSG = "Uninstall widget"; + +const char * const CONFIG_XML = "config.xml"; +const char * const HYBRID_CONFIG_XML = "res/wgt/config.xml"; + +const unsigned int NOFILE_CNT_FOR_INSTALLER = 9999; + +struct free_deleter +{ + void operator()(void* x) + { + free(x); + } +}; + +struct PluginInstallerData +{ + void* wrtInstaller; + std::string pluginPath; +}; +} // namespace anonymous + +WrtInstaller::WrtInstaller(int argc, char **argv) : + Application(argc, argv, "backend", false), + DPL::TaskDecl(this), + m_packagePath(), + m_initialized(false), + m_numPluginsToInstall(0), + m_totalPlugins(0), + m_returnStatus(-1), + m_installByPkgmgr(false), + m_startupPluginInstallation(false) +{ + Touch(); + _D("App Created"); +} + +WrtInstaller::~WrtInstaller() +{ + _D("App Finished"); +} + +int WrtInstaller::getReturnStatus() const +{ + return m_returnStatus; +} + +void WrtInstaller::OnStop() +{ + _D("Stopping Dummy Client"); +} + +void WrtInstaller::OnCreate() +{ + _D("Creating DummyClient"); + showArguments(); + + AddStep(&WrtInstaller::initStep); + + std::string arg = m_argv[0]; + + pkgmgrSignalInterface = + std::static_pointer_cast( + std::shared_ptr( + new PackageManager::PkgmgrSignalDummy() + ) + ); + + if (arg.empty()) { + return showHelpAndQuit(); + } + + installNewPlugins(); + + if (arg.find("wrt-installer") != std::string::npos) { + if (m_argc <= 1) { + return showHelpAndQuit(); + } + + arg = m_argv[1]; + if (arg == "-h" || arg == "--help") { + if (m_argc != 2) { + return showHelpAndQuit(); + } + + // Just show help + return showHelpAndQuit(); + } else if (arg == "-p" || arg == "--install-plugins") { + if (m_argc != 2) { + return showHelpAndQuit(); + } + + if (!m_startupPluginInstallation) { + AddStep(&WrtInstaller::installPluginsStep); + } else { + _D("Plugin installation alredy started"); + } + } else if (arg == "-i" || arg == "--install") { + if (m_argc != 3) { + return showHelpAndQuit(); + } + + struct stat info; + if (-1 != stat(m_argv[2], &info) && S_ISDIR(info.st_mode)) { + _D("Installing package directly from directory"); + m_installMode.extension = InstallMode::ExtensionType::DIR; + } else { + _D("Installing from regular location"); + m_installMode.extension = InstallMode::ExtensionType::WGT; + } + m_packagePath = m_argv[2]; + + AddStep(&WrtInstaller::installStep); + } else if (arg == "-ip" || arg == "--install-preload") { + _D("Install preload web app"); + if (m_argc != 3) { + return showHelpAndQuit(); + } + m_packagePath = m_argv[2]; + m_installMode.installTime = InstallMode::InstallTime::PRELOAD; + m_installMode.rootPath = InstallMode::RootPath::RO; + AddStep(&WrtInstaller::installStep); + } else if (arg == "-ipw" || arg == "--install-preload-writable") { + _D("Install preload web application to writable storage"); + if (m_argc != 3) { + return showHelpAndQuit(); + } + m_packagePath = m_argv[2]; + m_installMode.installTime = InstallMode::InstallTime::PRELOAD; + m_installMode.rootPath = InstallMode::RootPath::RW; + AddStep(&WrtInstaller::installStep); + } else if (arg == "-c" || arg == "--csc-update") { + // "path=/opt/system/csc/Ozq2iEG15R-2.0.0-arm.wgt:op=install:removable=true" + _D("Install & uninstall by csc configuration"); + if (m_argc != 3) { + return showHelpAndQuit(); + } + m_installMode.installTime = InstallMode::InstallTime::CSC; + std::string configuration = m_argv[2]; + m_CSCconfigurationMap = parseCSCConfiguration(configuration); + + CSCConfiguration::dataMap::iterator it; + it = m_CSCconfigurationMap.find(CSCConfiguration::KEY_OP); + if (it == m_CSCconfigurationMap.end()) { + return showHelpAndQuit(); + } + + if (it->second == CSCConfiguration::VALUE_INSTALL) { + _D("operation = %s", it->second.c_str()); + m_installMode.extension = InstallMode::ExtensionType::WGT; + it = m_CSCconfigurationMap.find(CSCConfiguration::KEY_PATH); + if (it == m_CSCconfigurationMap.end()) { + return showHelpAndQuit(); + } + m_packagePath = it->second; + + it = m_CSCconfigurationMap.find( + CSCConfiguration::KEY_REMOVABLE); + if (it == m_CSCconfigurationMap.end()) { + return showHelpAndQuit(); + } + + m_installMode.removable = + (it->second.compare(CSCConfiguration::VALUE_FALSE) == 0) + ? false : true; + + AddStep(&WrtInstaller::installStep); + _D("path = %s", m_packagePath.c_str()); + } else if (it->second == CSCConfiguration::VALUE_UNINSTALL) { + _D("operation = %s", it->second.c_str()); + // uninstall command isn't confirmed yet + it = m_CSCconfigurationMap.find(CSCConfiguration::KEY_PATH); + if (it == m_CSCconfigurationMap.end()) { + return showHelpAndQuit(); + } + m_packagePath = it->second; + AddStep(&WrtInstaller::unistallWgtFileStep); + _D("operation = uninstall"); + _D("path = %s", m_packagePath.c_str()); + } else { + _E("Unknown operation : %s", it->second.c_str()); + _D("operation = %s", it->second.c_str()); + return showHelpAndQuit(); + } + } else if (arg == "-un" || arg == "--uninstall-name") { + if (m_argc != 3) { + return showHelpAndQuit(); + } + m_name = m_argv[2]; + AddStep(&WrtInstaller::uninstallPkgNameStep); + } else if (arg == "-up" || arg == "--uninstall-packagepath") { + if (m_argc != 3) { + return showHelpAndQuit(); + } + m_packagePath = m_argv[2]; + AddStep(&WrtInstaller::unistallWgtFileStep); + } else if (arg == "-r" || arg == "--reinstall") { + if (m_argc != 3) { + return showHelpAndQuit(); + } + _D("Installing package directly from directory"); + m_installMode.command = InstallMode::Command::REINSTALL; + m_installMode.extension = InstallMode::ExtensionType::DIR; + m_packagePath = m_argv[2]; + AddStep(&WrtInstaller::installStep); + } else { + return showHelpAndQuit(); + } + } else if (arg.find("backend") != std::string::npos) { + using namespace PackageManager; + m_installByPkgmgr = true; + + auto pkgmgrSignal = std::shared_ptr( + new PackageManager::PkgmgrSignal() + ); + + pkgmgrSignal->initialize(m_argc, m_argv); + + PackageManager::PkgmgrSignal::RequestType reqType = pkgmgrSignal->getRequestedType(); + + pkgmgrSignalInterface = + std::static_pointer_cast( + pkgmgrSignal); + switch (reqType) { + case PackageManager::PkgmgrSignal::RequestType::INSTALL: + m_packagePath = m_argv[4]; + if (6 < m_argc) { + m_name = std::string(m_argv[6]); + } + + struct stat info; + if (-1 != stat(m_argv[4], &info) && S_ISDIR(info.st_mode)) { + _D("Installing package directly from directory"); + m_installMode.extension = InstallMode::ExtensionType::DIR; + } else { + _D("Installing from regular location"); + m_installMode.extension = InstallMode::ExtensionType::WGT; + } + AddStep(&WrtInstaller::installStep); + break; + case PackageManager::PkgmgrSignal::RequestType::UNINSTALL: + { + m_name = m_argv[4]; + pkgmgrinfo_pkginfo_h handle = NULL; + bool system_app = false; // system app is preloaded and unremovable. + bool update = false; + + if (0 == pkgmgrinfo_pkginfo_get_pkginfo(m_name.c_str(), &handle)) { + if (0 > pkgmgrinfo_pkginfo_is_system(handle, &system_app)) { + _E("Can't get package information : %s", m_name.c_str()); + } + if (0 > pkgmgrinfo_pkginfo_is_update(handle, &update)) { + _E("Can't get package information about update : %s", m_name.c_str()); + } + } + + _D("system app : %d", system_app); + _D("update : %d", update); + + if (system_app && update) { + AddStep(&WrtInstaller::removeUpdateStep); + } else { + AddStep(&WrtInstaller::uninstallPkgNameStep); + } + break; + } + case PackageManager::PkgmgrSignal::RequestType::REINSTALL: + m_packagePath = m_argv[4]; + m_installMode.command = InstallMode::Command::REINSTALL; + m_installMode.extension = InstallMode::ExtensionType::DIR; + AddStep(&WrtInstaller::installStep); + break; + default: + _D("Not available type"); + break; + } + } + + AddStep(&WrtInstaller::shutdownStep); + DPL::Event::ControllerEventHandler:: + PostEvent( + WRTInstallerNS::NextStepEvent()); +} + +void WrtInstaller::OnReset(bundle* /*b*/) +{ + _D("OnReset"); +} + +void WrtInstaller::OnTerminate() +{ + _D("Wrt Shutdown now"); + PluginUtils::unlockPluginInstallation( + m_installMode.installTime == InstallMode::InstallTime::PRELOAD); + if (m_initialized) { + wrt_installer_shutdown(); + } +} + +void WrtInstaller::showHelpAndQuit() +{ + printf("Usage: wrt-installer [OPTION]... [WIDGET: ID/NAME/PATH]...\n" + "Operate with WebRuntime daemon: install, uninstall" + " and launch widgets.\n" + "Query list of installed widgets and setup up debugging support.\n" + "\n" + "Exactly one option must be selected.\n" + "Mandatory arguments to long options are mandatory for short " + "options too.\n" + " -h, --help show this help\n" + " -p, --install-plugins install plugins\n" + " -i, --install " + "install or update widget package for given path\n" + " -c, --csc-update " + "install or uninstall by CSC configuration \n" + " -un, --uninstall-name " + "uninstall widget for given package name\n" + " -up, --uninstall-packagepath " + "uninstall widget for given package file path\n" + " -r, --reinstall " + "reinstall web application\n" + "\n"); + + Quit(); +} + +void WrtInstaller::showArguments() +{ + fprintf(stderr, + "===========================================================\n"); + fprintf(stderr, "# wrt-installer #\n"); + fprintf(stderr, "# argc [%d]\n", m_argc); + for (int i = 0; i < m_argc; i++) { + fprintf(stderr, "# argv[%d] = [%s]\n", i, m_argv[i]); + } + fprintf(stderr, + "===========================================================\n"); + // for dlog + _D("==========================================================="); + _D("# wrt-installer #"); + _D("# argc %d", m_argc); + for (int i = 0; i < m_argc; i++) { + _D("# argv[%d] = %s", i, m_argv[i]); + } + _D("==========================================================="); + +} + +void WrtInstaller::OnEventReceived(const WRTInstallerNS::QuitEvent& /*event*/) +{ + _D("Quiting"); + + if (m_initialized) { + _D("Wrt Shutdown now"); + SwitchToStep(&WrtInstaller::shutdownStep); + DPL::Event::ControllerEventHandler:: + PostEvent( + WRTInstallerNS::NextStepEvent()); + } else { + _D("Quiting application"); + return Quit(); + } +} + +void WrtInstaller::OnEventReceived( + const WRTInstallerNS::NextStepEvent& /*event*/) +{ + _D("Executing next step"); + NextStep(); +} + +void WrtInstaller::OnEventReceived( + const WRTInstallerNS::InstallPluginEvent& /*event*/) +{ + PluginInstallerData* privateData = new PluginInstallerData; + privateData->wrtInstaller = this; + + if (!(*m_pluginsPaths).empty()) { + privateData->pluginPath = (*m_pluginsPaths).front(); + (*m_pluginsPaths).pop_front(); + + wrt_install_plugin(privateData->pluginPath.c_str(), + static_cast(privateData), + &staticWrtPluginInstallationCallback, + &staticWrtPluginInstallProgressCb); + } else { + delete privateData; + } +} + +void WrtInstaller::initStep() +{ + wrt_installer_init(this, staticWrtInitCallback); +} + +void WrtInstaller::installStep() +{ + _D("Installing widget ..."); + std::unique_ptr packagePath(canonicalize_file_name( + m_packagePath.c_str())); + + wrt_install_widget(packagePath ? packagePath.get() : m_packagePath.c_str(), + m_name.c_str(), this, &staticWrtStatusCallback, + (m_installByPkgmgr) + ? &staticWrtInstallProgressCallback : NULL, + m_installMode, + pkgmgrSignalInterface); +} + +void WrtInstaller::installPluginsStep() +{ + _D("Installing plugins ..."); + fprintf(stderr, "Installing plugins ...\n"); + + if (m_startupPluginInstallation) { + _D("Plugin installation started because new plugin package found"); + } else if (!PluginUtils::lockPluginInstallation( + m_installMode.installTime == InstallMode::InstallTime::PRELOAD)) + { + _E("Failed to open plugin installation lock file" + " Plugins are currently installed by other process"); + staticWrtPluginInstallationCallback(WRT_INSTALLER_ERROR_PLUGIN_INSTALLATION_FAILED, + this); + return; + } + + std::string PLUGIN_PATH = std::string(GlobalConfig::GetDevicePluginPath()); + + DIR *dir; + dir = opendir(PLUGIN_PATH.c_str()); + + if (!dir) { + return; + } + + _D("Plugin DIRECTORY IS %s", PLUGIN_PATH.c_str()); + + std::list pluginsPaths; + struct dirent libdir; + struct dirent *result; + int return_code; + errno = 0; + for (return_code = readdir_r(dir, &libdir, &result); + result != NULL && return_code == 0; + return_code = readdir_r(dir, &libdir, &result)) + { + if (strcmp(libdir.d_name, ".") == 0 || + strcmp(libdir.d_name, "..") == 0) + { + continue; + } + + std::string path = PLUGIN_PATH; + path += "/"; + path += libdir.d_name; + + struct stat tmp; + + if (stat(path.c_str(), &tmp) == -1) { + _E("Failed to open file %s", path.c_str()); + continue; + } + + if (!S_ISDIR(tmp.st_mode)) { + _E("Not a directory %s", path.c_str()); + continue; + } + + pluginsPaths.push_back(path); + } + + if (return_code != 0 || errno != 0) { + _E("readdir_r() failed with %s", DPL::GetErrnoString().c_str()); + } + + //set nb of plugins to install + //this value indicate how many callbacks are expected + m_numPluginsToInstall = pluginsPaths.size(); + _D("Plugins to install: %d", m_numPluginsToInstall); + m_pluginsPaths = pluginsPaths; + + m_totalPlugins = m_numPluginsToInstall; + DPL::Event::ControllerEventHandler + ::PostEvent(WRTInstallerNS::InstallPluginEvent()); + + if (-1 == TEMP_FAILURE_RETRY(closedir(dir))) { + _E("Failed to close dir: %s with error: %s", PLUGIN_PATH.c_str(), DPL::GetErrnoString().c_str()); + } +} + +void WrtInstaller::uninstallPkgNameStep() +{ + _D("Uninstalling widget ..."); + _D("Package name : %s", m_name.c_str()); + + wrt_uninstall_widget(m_name.c_str(), this, + &staticWrtStatusCallback, + (m_installByPkgmgr) + ? &staticWrtUninstallProgressCallback : NULL, + pkgmgrSignalInterface); +} + +void WrtInstaller::removeUpdateStep() +{ + _D("This web app need to initialize preload app"); + _D("Package name : %s", m_name.c_str()); + + wrt_uninstall_widget(m_name.c_str(), this, + &staticWrtInitializeToPreloadCallback, + (m_installByPkgmgr) + ? &staticWrtUninstallProgressCallback : NULL, + pkgmgrSignalInterface); + +} + +void WrtInstaller::unistallWgtFileStep() +{ + _D("Uninstalling widget ..."); + + Try { + // Parse config + ParserRunner parser; + ConfigParserData configInfo; + + // Open zip file + std::unique_ptr zipFile( + new DPL::ZipInput(m_packagePath)); + std::unique_ptr configFile; + + Try { + // Open config.xml file + configFile.reset(zipFile->OpenFile(CONFIG_XML)); + } + Catch(DPL::ZipInput::Exception::OpenFileFailed) + { + // Open config.xml file for hybrid + configFile.reset(zipFile->OpenFile(HYBRID_CONFIG_XML)); + } + + // Extract config + DPL::BinaryQueue buffer; + DPL::AbstractWaitableInputAdapter inputAdapter(configFile.get()); + DPL::AbstractWaitableOutputAdapter outputAdapter(&buffer); + DPL::Copy(&inputAdapter, &outputAdapter); + parser.Parse(&buffer, + ElementParserPtr( + new RootParser(configInfo, + DPL::FromUTF32String( + L"widget")))); + + DPL::OptionalString pkgId = configInfo.tizenPkgId; + if (!pkgId.IsNull()) { + _D("Pkgid from packagePath : %ls", (*pkgId).c_str()); + wrt_uninstall_widget( + DPL::ToUTF8String(*pkgId).c_str(), this, &staticWrtStatusCallback, + !m_installByPkgmgr ? &staticWrtUninstallProgressCallback + : NULL, + pkgmgrSignalInterface); + } else { + _E("Fail to uninstalling widget... "); + m_returnStatus = -1; + DPL::Event::ControllerEventHandler:: + PostEvent( + WRTInstallerNS::QuitEvent()); + } + } + Catch(DPL::ZipInput::Exception::OpenFailed) + { + _E("Failed to open widget package"); + printf("failed: widget package does not exist\n"); + m_returnStatus = -1; + DPL::Event::ControllerEventHandler:: + PostEvent( + WRTInstallerNS::QuitEvent()); + } + Catch(DPL::ZipInput::Exception::OpenFileFailed) + { + printf("failed: widget config file does not exist\n"); + _E("Failed to open config.xml file"); + m_returnStatus = -1; + DPL::Event::ControllerEventHandler:: + PostEvent( + WRTInstallerNS::QuitEvent()); + } + Catch(ElementParser::Exception::ParseError) + { + printf("failed: can not parse config file\n"); + _E("Failed to parse config.xml file"); + m_returnStatus = -1; + DPL::Event::ControllerEventHandler:: + PostEvent( + WRTInstallerNS::QuitEvent()); + } +} + +void WrtInstaller::shutdownStep() +{ + _D("Closing Wrt connection ..."); + if (m_initialized) { + wrt_installer_shutdown(); + m_initialized = false; + DPL::Event::ControllerEventHandler:: + PostEvent( + WRTInstallerNS::QuitEvent()); + } +} + +void WrtInstaller::staticWrtInitCallback(WrtErrStatus status, + void* userdata) +{ + WrtInstaller *This = static_cast(userdata); + Assert(This); + + if (status == WRT_SUCCESS) { + _D("Init succesfull"); + This->m_initialized = true; + This->m_returnStatus = 0; + + This->DPL::Event::ControllerEventHandler + ::PostEvent(WRTInstallerNS::NextStepEvent()); + } else { + _E("Init unsuccesfull"); + This->m_returnStatus = -1; + This->DPL::Event::ControllerEventHandler:: + PostEvent( + WRTInstallerNS::QuitEvent()); + } +} + +void WrtInstaller::staticWrtInitializeToPreloadCallback(std::string tizenId, WrtErrStatus + status, void* userdata) +{ + WrtInstaller *This = static_cast(userdata); + Assert(This); + + std::string printMsg = "uninstallation"; + + if (WRT_SUCCESS != status) { + // Failure + _E("Step failed"); + This->m_returnStatus = 1; + + This->showErrorMsg(status, tizenId, printMsg); + + This->DPL::Event::ControllerEventHandler + ::PostEvent(WRTInstallerNS::QuitEvent()); + } else { + InstallMode mode; + mode.extension = InstallMode::ExtensionType::DIR; + mode.installTime = InstallMode::InstallTime::PRELOAD; + mode.rootPath = InstallMode::RootPath::RO; + std::string packagePath = + std::string(WrtDB::GlobalConfig::GetUserPreloadedWidgetPath()) + "/" + + This->m_name; + + wrt_install_widget(packagePath.c_str(), tizenId.c_str(), + This, &staticWrtInitPreloadStatusCallback, + NULL, + mode, + This->pkgmgrSignalInterface); + } +} + +void WrtInstaller::staticWrtInitPreloadStatusCallback(std::string tizenId, + WrtErrStatus status, + void* userdata) +{ + WrtInstaller *This = static_cast(userdata); + Assert(This); + + std::string printMsg = "initialization"; + + if (WRT_SUCCESS != status) { + // Failure + _E("Step failed"); + This->m_returnStatus = status; + + This->showErrorMsg(status, tizenId, printMsg); + + This->DPL::Event::ControllerEventHandler + ::PostEvent(WRTInstallerNS::QuitEvent()); + } else { + fprintf(stderr, + "## wrt-installer : %s %s was successful.\n", + tizenId.c_str(), + printMsg.c_str()); + _D("Status succesfull"); + This->m_returnStatus = 0; + + This->DPL::Event::ControllerEventHandler + ::PostEvent(WRTInstallerNS::NextStepEvent()); + } +} + +void WrtInstaller::staticWrtStatusCallback(std::string tizenId, + WrtErrStatus status, + void* userdata) +{ + WrtInstaller *This = static_cast(userdata); + Assert(This); + + Step current = This->GetCurrentStep(); + std::string printMsg; + + if (current == &WrtInstaller::installStep) { + printMsg = "installation"; + } else if (current == &WrtInstaller::uninstallPkgNameStep || + current == &WrtInstaller::unistallWgtFileStep) + { + printMsg = "uninstallation"; + } + + if (WRT_SUCCESS != status) { + // Failure + _E("Step failed"); + This->m_returnStatus = status; + + This->DPL::Event::ControllerEventHandler + ::PostEvent(WRTInstallerNS::QuitEvent()); + + This->showErrorMsg(status, tizenId, printMsg); + } else { + fprintf(stderr, + "## wrt-installer : %s %s was successful.\n", + tizenId.c_str(), + printMsg.c_str()); + _D("Status succesfull"); + This->m_returnStatus = 0; + + if (This->m_installMode.installTime == InstallMode::InstallTime::PRELOAD && + !This->m_packagePath.empty()) + { + _D("This widget is preloaded so it will be removed : %s", This->m_packagePath.c_str()); + if (!WrtUtilRemove(This->m_packagePath)) { + _E("Failed to remove %s", This->m_packagePath.c_str()); + } + } + + This->DPL::Event::ControllerEventHandler + ::PostEvent(WRTInstallerNS::NextStepEvent()); + } +} + +void WrtInstaller::showErrorMsg(WrtErrStatus status, std::string tizenId, + std::string printMsg) +{ + switch (status) { + case WRT_INSTALLER_ERROR_PACKAGE_NOT_FOUND: + fprintf(stderr, "## wrt-installer : %s %s has failed - widget package does not exist\n", + tizenId.c_str(), printMsg.c_str()); + break; + + case WRT_INSTALLER_ERROR_PACKAGE_INVALID: + fprintf(stderr, "## wrt-installer : %s %s has failed - invalid widget package\n", + tizenId.c_str(), printMsg.c_str()); + break; + + case WRT_INSTALLER_ERROR_PACKAGE_LOWER_VERSION: + fprintf(stderr, "## wrt-installer : %s %s has failed - given" + " version is lower than existing version\n", + tizenId.c_str(), printMsg.c_str()); + break; + + case WRT_INSTALLER_ERROR_MANIFEST_NOT_FOUND: + fprintf(stderr, "## wrt-installer : %s %s has failed - manifest" + " file doesn't find in package.\n", + tizenId.c_str(), printMsg.c_str()); + break; + + case WRT_INSTALLER_ERROR_MANIFEST_INVALID: + fprintf(stderr, "## wrt-installer : %s %s has failed - " + "invalid manifestx.xml\n", + tizenId.c_str(), printMsg.c_str()); + break; + + case WRT_INSTALLER_CONFIG_NOT_FOUND: + fprintf(stderr, "## wrt-installer : %s %s has failed - " + "config.xml does not exist\n", + tizenId.c_str(), printMsg.c_str()); + break; + + case WRT_INSTALLER_ERROR_CONFIG_INVALID: + fprintf(stderr, "## wrt-installer : %s %s has failed - " + "invalid config.xml\n", + tizenId.c_str(), printMsg.c_str()); + break; + + case WRT_INSTALLER_ERROR_SIGNATURE_NOT_FOUND: + fprintf(stderr, "## wrt-installer : %s %s has failed - " + "signature doesn't exist in package.\n", + tizenId.c_str(), printMsg.c_str()); + break; + + case WRT_INSTALLER_ERROR_SIGNATURE_INVALID: + fprintf(stderr, "## wrt-installer : %s %s has failed - " + "invalid signature.\n", + tizenId.c_str(), printMsg.c_str()); + break; + + case WRT_INSTALLER_ERROR_SIGNATURE_VERIFICATION_FAILED: + fprintf(stderr, "## wrt-installer : %s %s has failed - " + "signature verification failed.\n", + tizenId.c_str(), printMsg.c_str()); + break; + + case WRT_INSTALLER_ERROR_ROOT_CERTIFICATE_NOT_FOUND: + fprintf(stderr, "## wrt-installer : %s %s has failed - " + "root certificate could not find.\n", + tizenId.c_str(), printMsg.c_str()); + break; + + case WRT_INSTALLER_ERROR_CERTIFICATION_INVAID: + fprintf(stderr, "## wrt-installer : %s %s has failed - " + "invalid certification.\n", + tizenId.c_str(), printMsg.c_str()); + break; + + case WRT_INSTALLER_ERROR_CERTIFICATE_CHAIN_VERIFICATION_FAILED: + fprintf(stderr, "## wrt-installer : %s %s has failed - " + "certificate chain verification failed.\n", + tizenId.c_str(), printMsg.c_str()); + break; + + case WRT_INSTALLER_ERROR_CERTIFICATE_EXPIRED: + fprintf(stderr, "## wrt-installer : %s %s has failed - " + "certificate expired.\n", + tizenId.c_str(), printMsg.c_str()); + break; + + case WRT_INSTALLER_ERROR_INVALID_PRIVILEGE: + fprintf(stderr, "## wrt-installer : %s %s has failed - " + "invalid privilege\n", + tizenId.c_str(), printMsg.c_str()); + break; + + case WRT_INSTALLER_ERROR_PRIVILEGE_LEVEL_VIOLATION: + fprintf(stderr, "## wrt-installer : %s %s has failed - " + "privilege level violation\n", + tizenId.c_str(), printMsg.c_str()); + break; + + case WRT_INSTALLER_ERROR_MENU_ICON_NOT_FOUND: + fprintf(stderr, "## wrt-installer : %s %s has failed - " + "menu icon could not find\n", + tizenId.c_str(), printMsg.c_str()); + break; + + case WRT_INSTALLER_ERROR_FATAL_ERROR: + fprintf(stderr, "## wrt-installer : %s %s has failed - " + "fatal error\n", + tizenId.c_str(), printMsg.c_str()); + break; + + case WRT_INSTALLER_ERROR_OUT_OF_STORAGE: + fprintf(stderr, "## wrt-installer : %s %s has failed - " + "out of storage\n", + tizenId.c_str(), printMsg.c_str()); + break; + + case WRT_INSTALLER_ERROR_OUT_OF_MEMORY: + fprintf(stderr, "## wrt-installer : %s %s has failed - " + "out of memory\n", + tizenId.c_str(), printMsg.c_str()); + break; + + case WRT_INSTALLER_ERROR_ARGUMENT_INVALID: + fprintf(stderr, "## wrt-installer : %s %s has failed - " + "invalid argument\n", + tizenId.c_str(), printMsg.c_str()); + break; + + case WRT_INSTALLER_ERROR_PACKAGE_ALREADY_INSTALLED: + fprintf(stderr, "## wrt-installer : %s %s has failed - " + "package already installed\n", + tizenId.c_str(), printMsg.c_str()); + break; + + case WRT_INSTALLER_ERROR_ACE_CHECK_FAILED: + fprintf(stderr, "## wrt-installer : %s %s has failed - " + "ace check failure\n", + tizenId.c_str(), printMsg.c_str()); + break; + + case WRT_INSTALLER_ERROR_MANIFEST_CREATE_FAILED: + fprintf(stderr, "## wrt-installer : %s %s has failed - " + "to create manifest failed\n", + tizenId.c_str(), printMsg.c_str()); + break; + + case WRT_INSTALLER_ERROR_ENCRYPTION_FAILED: + fprintf(stderr, "## wrt-installer : %s %s has failed - " + "encryption of resource failed\n", + tizenId.c_str(), printMsg.c_str()); + break; + + case WRT_INSTALLER_ERROR_INSTALL_OSP_SERVCIE: + fprintf(stderr, "## wrt-installer : %s %s has failed - " + "installation of osp service failed\n", + tizenId.c_str(), printMsg.c_str()); + break; + + case WRT_INSTALLER_ERROR_UNINSTALLATION_FAILED: + fprintf(stderr, "## wrt-installer : %s %s has failed - " + "widget uninstallation failed\n", + tizenId.c_str(), printMsg.c_str()); + break; + + + case WRT_INSTALLER_ERROR_UNKNOWN: + fprintf(stderr,"## wrt-installer : %s %s has failed - unknown error\n", + tizenId.c_str(), printMsg.c_str()); + break; + + default: + break; + } + +} + +void WrtInstaller::staticWrtPluginInstallationCallback(WrtErrStatus status, + void* userdata) +{ + Assert(userdata); + + PluginInstallerData* data = static_cast(userdata); + + WrtInstaller *This = static_cast(data->wrtInstaller); + + std::string path = std::string(data->pluginPath); + delete data; + + This->m_numPluginsToInstall--; + _D("Plugins to install: %d", This->m_numPluginsToInstall); + + if (This->m_numPluginsToInstall < 1) { + _D("All plugins installation completed"); + fprintf(stderr, "All plugins installation completed.\n"); + + //remove installation request + if (!PluginUtils::removeInstallationRequiredFlag()) { + _D("Failed to remove file initializing plugin installation"); + } + + //remove lock file + if (!PluginUtils::unlockPluginInstallation( + This->m_installMode.installTime == InstallMode::InstallTime::PRELOAD)) + { + _D("Failed to remove installation lock"); + } + + This->DPL::Event::ControllerEventHandler + ::PostEvent(WRTInstallerNS::NextStepEvent()); + } else { + This->DPL::Event::ControllerEventHandler:: + PostEvent( + WRTInstallerNS::InstallPluginEvent()); + } + + if (WRT_SUCCESS == status) { + This->m_returnStatus = 0; + fprintf(stderr, + "## wrt-installer : plugin installation successfull [%s]\n", + path.c_str()); + _D("One plugin Installation succesfull: %s", path.c_str()); + return; + } + + // Failure + _W("One of the plugins installation failed!: %s", path.c_str()); + + switch (status) { + case WRT_INSTALLER_ERROR_PLUGIN_INSTALLATION_FAILED: + _E("failed: plugin installation failed\n"); + break; + + case WRT_INSTALLER_ERROR_UNKNOWN: + _E("failed: unknown error\n"); + break; + + default: + break; + } +} + +void WrtInstaller::staticWrtPluginInstallProgressCb(float percent, + const char* description, + void* userdata) +{ + PluginInstallerData* data = static_cast(userdata); + + std::string path = std::string(data->pluginPath); + + _D("Plugin Installation: %s progress: %2.0f description: %s", path.c_str(), percent, description); +} + +void WrtInstaller::staticWrtInstallProgressCallback(float percent, + const char* description, + void* /*userdata*/) +{ + //WrtInstaller *This = static_cast(userdata); + _D(" progress: %2.0f description: %s", percent, description); +} +void WrtInstaller::staticWrtUninstallProgressCallback(float percent, + const char* description, + void* /*userdata*/) +{ + //WrtInstaller *This = static_cast(userdata); + _D(" progress: %2.0f description: %s", percent, description); +} + +void WrtInstaller::installNewPlugins() +{ + _D("Install new plugins"); + + if (!PluginUtils::lockPluginInstallation( + m_installMode.installTime == InstallMode::InstallTime::PRELOAD)) + { + _D("Lock NOT created"); + return; + } + + if (!PluginUtils::checkPluginInstallationRequired()) { + _D("Plugin installation not required"); + PluginUtils::unlockPluginInstallation( + m_installMode.installTime == InstallMode::InstallTime::PRELOAD); + return; + } + + m_startupPluginInstallation = true; + AddStep(&WrtInstaller::installPluginsStep); +} + +CSCConfiguration::dataMap WrtInstaller::parseCSCConfiguration( + std::string str) +{ + // path=/opt/system/csc/Ozq2iEG15R-2.0.0-arm.wgt:op=install:removable=true + // parsing CSC configuration string + _D("parseConfiguration"); + CSCConfiguration::dataMap result; + + if (str.empty()) { + _D("Input argument is empty"); + return result; + } + + char* buf = strdup(str.c_str()); + const char* ptr = strtok(buf,":"); + while (ptr != NULL) { + std::string string = ptr; + ptr = strtok (NULL, ":"); + size_t pos = string.find('='); + if (pos == std::string::npos) { + continue; + } + result.insert( + CSCConfiguration::dataPair(string.substr(0, pos), + string.substr(pos+1))); + } + free(buf); + return result; +} + +int main(int argc, char *argv[]) +{ + UNHANDLED_EXCEPTION_HANDLER_BEGIN + { + DPL::Log::LogSystemSingleton::Instance().SetTag("WRT_INSTALLER"); + + // Output on stdout will be flushed after every newline character, + // even if it is redirected to a pipe. This is useful for running + // from a script and parsing output. + // (Standard behavior of stdlib is to use full buffering when + // redirected to a pipe, which means even after an end of line + // the output may not be flushed). + setlinebuf(stdout); + + // Check and re-set the file open limitation + struct rlimit rlim; + if (getrlimit(RLIMIT_NOFILE, &rlim) != -1) { + _D("RLIMIT_NOFILE sft(%d)", rlim.rlim_cur); + _D("RLIMIT_NOFILE hrd(%d)", rlim.rlim_max); + + if (rlim.rlim_cur < NOFILE_CNT_FOR_INSTALLER) { + rlim.rlim_cur = NOFILE_CNT_FOR_INSTALLER; + rlim.rlim_max = NOFILE_CNT_FOR_INSTALLER; + if (setrlimit(RLIMIT_NOFILE, &rlim) == -1) { + _E("setrlimit is fail!!"); + } + } + } else { + _E("getrlimit is fail!!"); + } + + WrtInstaller app(argc, argv); + int ret = app.Exec(); + _D("App returned: %d", ret); + ret = app.getReturnStatus(); + _D("WrtInstaller returned: %d", ret); + return ret; + } + UNHANDLED_EXCEPTION_HANDLER_END +} diff --git a/src_mobile/wrt-installer/wrt-installer.h b/src_mobile/wrt-installer/wrt-installer.h new file mode 100644 index 0000000..e8feefb --- /dev/null +++ b/src_mobile/wrt-installer/wrt-installer.h @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file wrt-installer.h + * @version 1.0 + * @brief Implementation file for installer + */ +#ifndef WRT_INSTALLER_H +#define WRT_INSTALLER_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace WRTInstallerNS { //anonymous +DECLARE_GENERIC_EVENT_0(QuitEvent) +DECLARE_GENERIC_EVENT_0(NextStepEvent) +DECLARE_GENERIC_EVENT_0(InstallPluginEvent) +} + +typedef void (*ShowResultCallback)(void *data, Evas_Object *obj, + void *event_info); +namespace CSCConfiguration { +typedef std::map dataMap; +typedef std::pair dataPair; +const char* const KEY_OP = "op"; +const char* const KEY_PATH = "path"; +const char* const KEY_REMOVABLE = "removable"; +const char* const VALUE_INSTALL = "install"; +const char* const VALUE_UNINSTALL = "uninstall"; +const char* const VALUE_TRUE = "true"; +const char* const VALUE_FALSE = "false"; +} + +class WrtInstaller : + public DPL::Application, + private DPL::Event::Controller:: + Type>, + public DPL::TaskDecl +{ + public: + WrtInstaller(int argc, + char **argv); + virtual ~WrtInstaller(); + + int getReturnStatus() const; + + protected: + virtual void OnStop(); + virtual void OnCreate(); + virtual void OnReset(bundle *b); + virtual void OnTerminate(); + + private: + void showHelpAndQuit(); + void showArguments(); + + // Events + virtual void OnEventReceived(const WRTInstallerNS::QuitEvent &event); + virtual void OnEventReceived(const WRTInstallerNS::NextStepEvent& event); + virtual void OnEventReceived( + const WRTInstallerNS::InstallPluginEvent& event); + + // Installation steps + void initStep(); + void installStep(); + void installPluginsStep(); + void uninstallPkgNameStep(); + void unistallWgtFileStep(); + void removeUpdateStep(); + void shutdownStep(); + + // Static callbacks + static void staticWrtInitCallback(WrtErrStatus status, + void* userdata); + static void staticWrtStatusCallback(std::string tizenId, + WrtErrStatus status, + void* userdata); + static void staticWrtPluginInstallationCallback(WrtErrStatus status, + void* userdata); + static void staticWrtPluginInstallProgressCb(float percent, + const char* description, + void* userdata); + static void staticWrtInstallProgressCallback(float percent, + const char* description, + void* userdata); + + static void staticWrtUninstallProgressCallback(float percent, + const char* description, + void* userdata); + + static void staticWrtInitializeToPreloadCallback(std::string tizenId, + WrtErrStatus status, + void* userdata); + + static void staticWrtInitPreloadStatusCallback(std::string tizenId, + WrtErrStatus status, + void* userdata); + + void installNewPlugins(); + CSCConfiguration::dataMap parseCSCConfiguration(std::string str); + void showErrorMsg(WrtErrStatus status, std::string tizenId, std::string + printMsg); + + // Private data + std::shared_ptr pkgmgrSignalInterface; + InstallMode m_installMode; + std::string m_packagePath; + std::string m_name; + bool m_initialized; + size_t m_numPluginsToInstall; + size_t m_totalPlugins; + int m_returnStatus; + bool m_installByPkgmgr; + bool m_startupPluginInstallation; + CSCConfiguration::dataMap m_CSCconfigurationMap; + + typedef std::list PluginPathList; + DPL::Optional m_pluginsPaths; +}; +#endif // WRT_INSTALLER_H diff --git a/src_mobile/wrt-installer/wrt_installer_api.cpp b/src_mobile/wrt-installer/wrt_installer_api.cpp new file mode 100644 index 0000000..ba1ee19 --- /dev/null +++ b/src_mobile/wrt-installer/wrt_installer_api.cpp @@ -0,0 +1,254 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file wrt_installer_api.cpp + * @author Chung Jihoon (jihoon.chung@samsung.com) + * @version 1.0 + * @brief This file contains definitions of wrt installer api + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace WrtDB; + +static std::string cutOffFileName(const std::string& path) +{ + size_t found = path.find_last_of("/"); + if (found == std::string::npos) { + return path; + } else { + return path.substr(0, found); + } +} + +static bool checkPath(const std::string& path) +{ + struct stat st; + if (0 == stat(path.c_str(), &st) && S_ISDIR(st.st_mode)) { + return true; + } + _E("Cannot access directory [ %s ]", path.c_str()); + return false; +} + +static bool checkPaths() +{ + bool if_ok = true; + + if_ok &= (checkPath(cutOffFileName(GlobalConfig::GetWrtDatabaseFilePath()))); + if_ok &= (checkPath(GlobalConfig::GetDevicePluginPath())); + if_ok &= (checkPath(GlobalConfig::GetUserInstalledWidgetPath())); + if_ok &= (checkPath(GlobalConfig::GetUserPreloadedWidgetPath())); + + return if_ok; +} + +void wrt_installer_init(void *userdata, + WrtInstallerInitCallback callback) +{ + try { + _D("[WRT-API] INITIALIZING WRT INSTALLER..."); + _D("[WRT-API] BUILD: %s", __TIMESTAMP__); + + // Touch InstallerController Singleton + InstallerMainThreadSingleton::Instance().TouchArchitecture(); + + // Check paths + if (!checkPaths()) { + if (callback) { + callback(WRT_INSTALLER_ERROR_FATAL_ERROR, userdata); + } + return; + } + + // Initialize ValidationCore - this must be done before AttachDatabases + ValidationCore::VCoreInit( + std::string(GlobalConfig::GetFingerprintListFile()), + std::string(GlobalConfig::GetFingerprintListSchema()), + std::string(GlobalConfig::GetVCoreDatabaseFilePath())); + + InstallerMainThreadSingleton::Instance().AttachDatabases(); + + _D("Prepare libxml2 to work in multithreaded program."); + xmlInitParser(); + + // Initialize Language Subtag registry + LanguageSubtagRstTreeSingleton::Instance().Initialize(); + + // Installer init + CONTROLLER_POST_SYNC_EVENT( + Logic::InstallerController, + InstallerControllerEvents:: + InitializeEvent()); + + if (callback) { + _D("[WRT-API] WRT INSTALLER INITIALIZATION CALLBACK"); + callback(WRT_SUCCESS, userdata); + } + } catch (const DPL::Exception& ex) { + _E("Internal Error during Init:"); + DPL::Exception::DisplayKnownException(ex); + if (callback) { + callback(WRT_INSTALLER_ERROR_FATAL_ERROR, userdata); + return; + } + } + return; +} + +void wrt_installer_shutdown() +{ + try { + _D("[WRT-API] DEINITIALIZING WRT INSTALLER..."); + + // Installer termination + CONTROLLER_POST_SYNC_EVENT( + Logic::InstallerController, + InstallerControllerEvents:: + TerminateEvent()); + + InstallerMainThreadSingleton::Instance().DetachDatabases(); + + // This must be done after DetachDatabase + ValidationCore::VCoreDeinit(); + + // Global deinit check + _D("Cleanup libxml2 global values."); + xmlCleanupParser(); + } catch (const DPL::Exception& ex) { + _E("Internal Error during Shutdown:"); + DPL::Exception::DisplayKnownException(ex); + } +} + +void wrt_install_widget( + const char *path, + const char *tzPkgId, + void* userdata, + WrtInstallerStatusCallback status_cb, + WrtProgressCallback progress_cb, + InstallMode installMode, + std::shared_ptr pkgmgrInterface + ) +{ + UNHANDLED_EXCEPTION_HANDLER_BEGIN + { + if (InstallMode::InstallTime::PRELOAD == installMode.installTime) { + DPL::Log::OldStyleLogProvider *oldStyleProvider = + new DPL::Log::OldStyleLogProvider(false, false, false, true, + false, true); + DPL::Log::LogSystemSingleton::Instance().AddProvider(oldStyleProvider); + } + + _D("[WRT-API] INSTALL WIDGET: %s", path); + // Post installation event + CONTROLLER_POST_EVENT( + Logic::InstallerController, + InstallerControllerEvents::InstallWidgetEvent( + path, tzPkgId, Jobs::WidgetInstall::WidgetInstallationStruct( + InstallerCallbacksTranslate::installFinishedCallback, + InstallerCallbacksTranslate::installProgressCallback, + new InstallerCallbacksTranslate::StatusCallbackStruct( + userdata, status_cb, progress_cb), + installMode, + pkgmgrInterface))); + } + UNHANDLED_EXCEPTION_HANDLER_END +} + +void wrt_uninstall_widget( + const char * const tzAppid, + void* userdata, + WrtInstallerStatusCallback status_cb, + WrtProgressCallback progress_cb, + std::shared_ptr pkgmgrSignalInterface) +{ + UNHANDLED_EXCEPTION_HANDLER_BEGIN + { + std::string tizenAppid(tzAppid); + _D("[WRT-API] UNINSTALL WIDGET: %s", tizenAppid.c_str()); + // Post uninstallation event + CONTROLLER_POST_EVENT( + Logic::InstallerController, + InstallerControllerEvents::UninstallWidgetEvent( + tizenAppid, + WidgetUninstallationStruct( + InstallerCallbacksTranslate::uninstallFinishedCallback, + InstallerCallbacksTranslate::installProgressCallback, + new InstallerCallbacksTranslate::StatusCallbackStruct( + userdata, status_cb, progress_cb), + pkgmgrSignalInterface + ) + ) + ); + } + UNHANDLED_EXCEPTION_HANDLER_END +} + +void wrt_install_plugin( + const char *pluginDir, + void *user_param, + WrtPluginInstallerStatusCallback status_cb, + WrtProgressCallback progress_cb) +{ + UNHANDLED_EXCEPTION_HANDLER_BEGIN + { + _D("[WRT-API] INSTALL PLUGIN: %s", pluginDir); + //Private data for status callback + //Resource is free in pluginInstallFinishedCallback + InstallerCallbacksTranslate::PluginStatusCallbackStruct* + callbackStruct = + new InstallerCallbacksTranslate::PluginStatusCallbackStruct( + user_param, status_cb, progress_cb); + + CONTROLLER_POST_EVENT( + Logic::InstallerController, + InstallerControllerEvents::InstallPluginEvent( + std::string(pluginDir), + PluginInstallerStruct( + InstallerCallbacksTranslate:: + pluginInstallFinishedCallback, + InstallerCallbacksTranslate:: + installProgressCallback, callbackStruct))); + } + UNHANDLED_EXCEPTION_HANDLER_END +} diff --git a/src_mobile/wrt-installer/wrt_installer_api.h b/src_mobile/wrt-installer/wrt_installer_api.h new file mode 100644 index 0000000..eb2be3c --- /dev/null +++ b/src_mobile/wrt-installer/wrt_installer_api.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file wrt_installer_api.h + * @author Chung Jihoon (jihoon.chung@samsung.com) + * @version 1.0 + * @brief This file contains declarations of wrt_installer_api + */ + +#ifndef WRT_INSTALLER_API_H_ +#define WRT_INSTALLER_API_H_ + +#include +#include +#include +#include +#include +#include +#include + +typedef void (*WrtInstallerInitCallback)(WrtErrStatus status, + void *data); +typedef void (*WrtPluginInstallerStatusCallback)(WrtErrStatus status, + void *data); +typedef void (*WrtInstallerStatusCallback)(std::string tizenId, + WrtErrStatus status, + void *data); +typedef void (*WrtProgressCallback)(float percent, + const char *description, + void *data); + +void wrt_installer_init( + void *userdata, + WrtInstallerInitCallback callback); +void wrt_installer_shutdown(void); +void wrt_install_widget( + const char *path, + const char *tzPkgId, + void *user_parameter, + WrtInstallerStatusCallback status_callback, + WrtProgressCallback progress_callback, + InstallMode install_mode, + std::shared_ptr + pkgmgrInterface + ); +void wrt_uninstall_widget ( + const char * const tzAppid, + void* userdata, + WrtInstallerStatusCallback status_cb, + WrtProgressCallback progress_cb, + std::shared_ptr + pkgmgrSignalInterface); +void wrt_install_plugin(const char *pluginDirectory, + void *userData, + WrtPluginInstallerStatusCallback statusCallback, + WrtProgressCallback progressCallback); + +#endif /* WRT_INSTALLER_API_H_ */ diff --git a/src_mobile/wrt-installer/wrt_type.h b/src_mobile/wrt-installer/wrt_type.h new file mode 100644 index 0000000..2cfb584 --- /dev/null +++ b/src_mobile/wrt-installer/wrt_type.h @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file wrt_type.h + * @author jihoon Chung (jihoon.Chung@samsung.com) + * @version 1.0 + * @brief This file contains declarations of wrt api + */ + +/* + * @defgroup wrt_engine_group WebRunTime engine Library + * @ingroup internet_FW + * Functions to APIs to access wrt-engine + */ + +#ifndef WRT_TYPE_H_ +#define WRT_TYPE_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define WRT_DEPRECATED __attribute__((deprecated)) + +typedef enum +{ + /* Generic success */ + WRT_SUCCESS = 0, /*< Success*/ + + /* pkgmgr error */ + WRT_INSTALLER_ERROR_PACKAGE_NOT_FOUND, ///< + WRT_INSTALLER_ERROR_PACKAGE_INVALID, ///< invalid widget package + WRT_INSTALLER_ERROR_PACKAGE_LOWER_VERSION, ///< given version is lower than existing version + WRT_INSTALLER_ERROR_PACKAGE_EXCUTABLE_NOT_FOUND, + + WRT_INSTALLER_ERROR_MANIFEST_NOT_FOUND = 11,///< + WRT_INSTALLER_ERROR_MANIFEST_INVALID, ///< + WRT_INSTALLER_CONFIG_NOT_FOUND, ///< couldn't find config.xml + ///< in package. + WRT_INSTALLER_ERROR_CONFIG_INVALID, ///< invalid config.xml + + WRT_INSTALLER_ERROR_SIGNATURE_NOT_FOUND = 21, ///< signature file not exist. + WRT_INSTALLER_ERROR_SIGNATURE_INVALID, ///< invalid signature file + WRT_INSTALLER_ERROR_SIGNATURE_VERIFICATION_FAILED, ///< failure in verificate signature + WRT_INSTALLER_ERROR_ROOT_CERTIFICATE_NOT_FOUND = 31, ///< couldn't find root certificate. + WRT_INSTALLER_ERROR_CERTIFICATION_INVAID, ///< invalid certification + WRT_INSTALLER_ERROR_CERTIFICATE_CHAIN_VERIFICATION_FAILED, ///< failure in verificate certification chain. + WRT_INSTALLER_ERROR_CERTIFICATE_EXPIRED, ///< expire cerification. + + WRT_INSTALLER_ERROR_INVALID_PRIVILEGE = 41, ///< invalid privilege. + WRT_INSTALLER_ERROR_PRIVILEGE_LEVEL_VIOLATION, + + WRT_INSTALLER_ERROR_MENU_ICON_NOT_FOUND = 51, ///< + + WRT_INSTALLER_ERROR_FATAL_ERROR = 61, ///< failure in db operation or file opertion.. + WRT_INSTALLER_ERROR_OUT_OF_STORAGE, ///< failure in shortage of memory + WRT_INSTALLER_ERROR_OUT_OF_MEMORY, ///< failure in shortage of RAM + WRT_INSTALLER_ERROR_ARGUMENT_INVALID, + + /* wrt-installer error */ + /* 121-140 : reserved for Web installer */ + + /* installation */ + WRT_INSTALLER_ERROR_PACKAGE_ALREADY_INSTALLED = 121, + WRT_INSTALLER_ERROR_ACE_CHECK_FAILED, + WRT_INSTALLER_ERROR_MANIFEST_CREATE_FAILED, ///< + WRT_INSTALLER_ERROR_ENCRYPTION_FAILED, ///< Failure in reousrce encrypttion + WRT_INSTALLER_ERROR_INSTALL_OSP_SERVCIE, ///< Failure in installing osp service + WRT_INSTALLER_ERROR_PLUGIN_INSTALLATION_FAILED, + WRT_INSTALLER_ERROR_UNINSTALLATION_FAILED, + + WRT_INSTALLER_ERROR_UNKNOWN = 140, ///< do not use this error code. + +} WrtErrStatus; + +#ifdef __cplusplus +} +#endif + +#endif /* WRT_TYPE_H_ */ diff --git a/src_wearable/CMakeLists.txt b/src_wearable/CMakeLists.txt new file mode 100755 index 0000000..ee25b20 --- /dev/null +++ b/src_wearable/CMakeLists.txt @@ -0,0 +1,186 @@ +# Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# @file CMakeLists.txt +# @author Lukasz Wrzosek (l.wrzosek@samsung.com) +# @version 1.0 +# + +SET(TARGET_INSTALLER "wrt-installer") + +OPTION(LB_SUPPORT "lb support" OFF) + +SET(INSTALLER_SRC_DIR + ${PROJECT_SOURCE_DIR}/src + ) + +SET(INSTALLER_CONFIG_PARSER + ${INSTALLER_SRC_DIR}/configuration_parser + ) + +SET(INSTALLER_JOBS + ${INSTALLER_SRC_DIR}/jobs + ) + +SET(INSTALLER_INCLUDES + ${INSTALLER_SRC_DIR} + ${INSTALLER_SRC_DIR}/logic + ${INSTALLER_SRC_DIR}/jobs + ${INSTALLER_SRC_DIR}/jobs/plugin_install + ${INSTALLER_SRC_DIR}/jobs/widget_install + ${INSTALLER_SRC_DIR}/jobs/widget_uninstall + ${INSTALLER_SRC_DIR}/misc + ${INSTALLER_SRC_DIR}/configuration_parser + ${INSTALLER_SRC_DIR}/wrt-installer + ${INSTALLER_SRC_DIR}/commons + ${INSTALLER_SRC_DIR}/pkg-manager +) + +SET(INSTALLER_SOURCES + ${INSTALLER_CONFIG_PARSER}/widget_parser.cpp + ${INSTALLER_CONFIG_PARSER}/parser_runner.cpp + ${INSTALLER_CONFIG_PARSER}/ignoring_parser.cpp + ${INSTALLER_CONFIG_PARSER}/deny_all_parser.cpp + ${INSTALLER_CONFIG_PARSER}/libiriwrapper.cpp + ${INSTALLER_JOBS}/job.cpp + ${INSTALLER_JOBS}/plugin_install/job_plugin_install.cpp + ${INSTALLER_JOBS}/plugin_install/plugin_install_task.cpp + ${INSTALLER_JOBS}/plugin_install/plugin_objects.cpp + ${INSTALLER_JOBS}/plugin_install/plugin_metafile_reader.cpp + ${INSTALLER_JOBS}/widget_install/job_widget_install.cpp + ${INSTALLER_JOBS}/widget_install/manifest.cpp + ${INSTALLER_JOBS}/widget_install/task_commons.cpp + ${INSTALLER_JOBS}/widget_install/task_process_config.cpp + ${INSTALLER_JOBS}/widget_install/task_database.cpp + ${INSTALLER_JOBS}/widget_install/task_configuration.cpp + ${INSTALLER_JOBS}/widget_install/ace_registration.cpp + ${INSTALLER_JOBS}/widget_install/task_file_manipulation.cpp + ${INSTALLER_JOBS}/widget_install/task_user_data_manipulation.cpp + ${INSTALLER_JOBS}/widget_install/task_smack.cpp + ${INSTALLER_JOBS}/widget_install/task_ace_check.cpp + ${INSTALLER_JOBS}/widget_install/task_manifest_file.cpp + ${INSTALLER_JOBS}/widget_install/task_certify.cpp + ${INSTALLER_JOBS}/widget_install/task_certify_level.cpp + ${INSTALLER_JOBS}/widget_install/task_prepare_files.cpp + ${INSTALLER_JOBS}/widget_install/task_recovery.cpp + ${INSTALLER_JOBS}/widget_install/task_install_ospsvc.cpp + ${INSTALLER_JOBS}/widget_install/task_update_files.cpp + ${INSTALLER_JOBS}/widget_install/task_remove_backup.cpp + ${INSTALLER_JOBS}/widget_install/task_encrypt_resource.cpp + ${INSTALLER_JOBS}/widget_install/task_prepare_reinstall.cpp + ${INSTALLER_JOBS}/widget_install/task_pkg_info_update.cpp + ${INSTALLER_JOBS}/widget_install/task_status_check.cpp + ${INSTALLER_JOBS}/widget_install/task_recovery.cpp + ${INSTALLER_JOBS}/widget_install/widget_security.cpp + ${INSTALLER_JOBS}/widget_install/directory_api.cpp + ${INSTALLER_JOBS}/widget_install/widget_unzip.cpp + ${INSTALLER_JOBS}/widget_uninstall/job_widget_uninstall.cpp + ${INSTALLER_JOBS}/widget_uninstall/task_check.cpp + ${INSTALLER_JOBS}/widget_uninstall/task_remove_files.cpp + ${INSTALLER_JOBS}/widget_uninstall/task_remove_custom_handlers.cpp + ${INSTALLER_JOBS}/widget_uninstall/task_db_update.cpp + ${INSTALLER_JOBS}/widget_uninstall/task_smack.cpp + ${INSTALLER_JOBS}/widget_uninstall/task_uninstall_ospsvc.cpp + ${INSTALLER_JOBS}/widget_uninstall/task_delete_pkginfo.cpp + ${INSTALLER_SRC_DIR}/logic/installer_logic.cpp + ${INSTALLER_SRC_DIR}/logic/installer_controller.cpp + ${INSTALLER_SRC_DIR}/misc/wac_widget_id.cpp + ${INSTALLER_SRC_DIR}/misc/feature_logic.cpp + ${INSTALLER_SRC_DIR}/misc/libxml_utils.cpp + ${INSTALLER_SRC_DIR}/misc/widget_location.cpp + ${INSTALLER_SRC_DIR}/misc/widget_install_to_external.cpp + ${INSTALLER_SRC_DIR}/misc/plugin_path.cpp + ${INSTALLER_SRC_DIR}/pkg-manager/pkgmgr_signal.cpp + ) + +IF(LB_SUPPORT) + SET(INSTALLER_SOURCES + ${INSTALLER_SOURCES} + ) + MESSAGE(STATUS "adding definition -DLB_SUPPORT") + ADD_DEFINITIONS("-DLB_SUPPORT") +ENDIF(LB_SUPPORT) + +MESSAGE(STATUS "add -DSEP_INSTALLER") +ADD_DEFINITIONS("-DSEP_INSTALLER") + + +PKG_CHECK_MODULES(INSTALLER_STATIC_DEP + dpl-efl + dpl-event-efl + dpl-utils-efl + dpl-wrt-dao-ro + dpl-wrt-dao-rw + wrt-commons-custom-handler-dao-rw + wrt-commons-security-origin-dao + wrt-commons-widget-interface-dao + wrt-plugins-types + pkgmgr-installer + pkgmgr-parser + pkgmgr-info + web-provider + libsmack + REQUIRED +) + +PKG_CHECK_MODULES(SYS_INSTALLER_STATIC_DEP + appsvc + libxml-2.0 + openssl + cert-svc-vcore + security-install + ecore-x + xmlsec1 + libidn + libiri + libpcrecpp + ail + elementary + tapi + shortcut + capi-appfw-app-manager + app2sd + libprivilege-control + REQUIRED +) + +INCLUDE_DIRECTORIES( SYSTEM ${SYS_INSTALLER_STATIC_DEP_INCLUDE_DIRS}) + +INCLUDE_DIRECTORIES( + ${INSTALLER_DEP_INCLUDES} + ${INSTALLER_INCLUDES} + ${INSTALLER_STATIC_DEP_INCLUDE_DIRS} + ${OSP_APPFW_INCLUDES} + ) + +ADD_LIBRARY(${TARGET_INSTALLER_STATIC} STATIC + ${INSTALLER_SOURCES} + ) + +ADD_DEFINITIONS(${INSTALLER_STATIC_DEP_CFLAGS}) +ADD_DEFINITIONS(${INSTALLER_STATIC_DEP_CFLAGS_OTHERS}) +ADD_DEFINITIONS(${SYS_INSTALLER_STATIC_DEP_CFLAGS}) +ADD_DEFINITIONS(${SYS_INSTALLER_STATIC_DEP_CFLAGS_OTHERS}) + +TARGET_LINK_LIBRARIES(${TARGET_INSTALLER_STATIC} + ${INSTALLER_STATIC_DEP_LIBRARIES} "-ldl" + ${SYS_INSTALLER_STATIC_DEP_LIBRARIES} "-ldl" + ) + +#for encryption +TARGET_LINK_LIBRARIES(${TARGET_INSTALLER_STATIC} "-lss-client" ) + +ADD_SUBDIRECTORY(pkg-manager) +ADD_SUBDIRECTORY(wrt-installer) diff --git a/src_wearable/DESCRIPTION b/src_wearable/DESCRIPTION new file mode 100644 index 0000000..0e8c571 --- /dev/null +++ b/src_wearable/DESCRIPTION @@ -0,0 +1,2 @@ +!!!options!!! stop +Widget (un)installer, plugin (un)installer diff --git a/src_wearable/commons/installer_log.h b/src_wearable/commons/installer_log.h new file mode 100755 index 0000000..500f405 --- /dev/null +++ b/src_wearable/commons/installer_log.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file installer_log.h + * @author Sungsu Kim(sung-su.kim@samsung.com) + * @version 0.1 + * @brief + */ + +#ifndef INSTALLER_LOG_H +#define INSTALLER_LOG_H + +#include +#include + +#include + +#ifdef WRT_INSTALLER_LOG + +#undef COLOR_WARNING +#define COLOR_WARNING "\e[0m" +#undef COLOR_TAG +#define COLOR_TAG "\e[0m" + +#endif + +// For FOTA debuging +#if 0 +#define PKGMGR_FOTA_PATH "/opt/share/packages/.recovery/fota/" +#define FOTA_RESULT_FILE PKGMGR_FOTA_PATH"result.txt" + +#define _FLOG(prio, fmt, arg...) do { \ + int __fd = 0;\ + FILE* __file = NULL;\ + __file = fopen(FOTA_RESULT_FILE, "a");\ + if (__file == NULL) break;\ + fprintf(__file, "[PKG_FOTA] [wrt-installer] [%s] [%s:%d] "fmt"\n", prio, __FUNCTION__, __LINE__, ##arg); \ + fflush(__file);\ + __fd = fileno(__file);\ + fsync(__fd);\ + fclose(__file);\ +} while (0) + +#undef _D +#define _D(fmt, arg ...) _FLOG("D", fmt, ##arg) + +#undef _W +#define _W(fmt, arg ...) _FLOG("W", fmt, ##arg) + +#undef _E +#define _E(fmt, arg ...) _FLOG("E", fmt, ##arg) +#endif + + +#endif // INSTALLER_LOG_H + diff --git a/src_wearable/commons/wrt_common_types.h b/src_wearable/commons/wrt_common_types.h new file mode 100644 index 0000000..cfed08f --- /dev/null +++ b/src_wearable/commons/wrt_common_types.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * plugin_common_types.h + * + * Author: Soyoung Kim(sy037.kim@samsung.com) + */ + +#ifndef PLUGIN_COMMON_TYPES_H +#define PLUGIN_COMMON_TYPES_H + +#include +#include +#include + +/** + * Widget version is optional + */ +typedef boost::optional OptionalWidgetVersion; + +/* Define db type */ +typedef WrtDB::DbWidgetFeature WidgetFeature; +typedef WrtDB::DbWidgetFeatureSet WidgetFeatureSet; + +typedef WrtDB::DbWidgetSize WidgetSize; + +typedef WrtDB::DbPluginHandle PluginHandle; + +enum InstallLocationType +{ + INSTALL_LOCATION_TYPE_UNKNOWN = 0, + INSTALL_LOCATION_TYPE_INTERNAL_ONLY, + INSTALL_LOCATION_TYPE_AUTO, + INSTALL_LOCATION_TYPE_PREFER_EXTERNAL, +}; + +#endif /* PLUGIN_COMMON_TYPES_H */ diff --git a/src_wearable/commons/wrt_error.h b/src_wearable/commons/wrt_error.h new file mode 100644 index 0000000..ae4f2de --- /dev/null +++ b/src_wearable/commons/wrt_error.h @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * This file contains the declaration of the error codes of Widget. + * + * @file wrt_error.h + * @author MaQuan (jason.ma@samsung.com) + * @version 0.7 + * @brief This file contains the declaration of the error codes of Widget. + */ + +#ifndef _WRT_ERROR_H_ +#define _WRT_ERROR_H_ + +#ifndef WRT_ERROR_MASKL8 +#define WRT_ERROR_MASKL8 0xFF +#endif + +#ifndef WRT_SET_IDENT +#define WRT_SET_IDENT(X) (X & WRT_ERROR_MASKL8) +#endif + +#ifndef WRT_ERROR_SET +#define WRT_ERROR_SET(X) ((X & WRT_ERROR_MASKL8) << 8) +#endif + +#define WRT_MID_ERRCODE 0x10000 + WRT_SET_IDENT(5) + +/*typedef */ enum +{ + WRT_GENERAL_ERRCODE = WRT_MID_ERRCODE + WRT_SET_IDENT(0), + WRT_CONFIG_ERRCODE = WRT_MID_ERRCODE + WRT_SET_IDENT(1), + WRT_DOMAIN_ERRCODE = WRT_MID_ERRCODE + WRT_SET_IDENT(2), + WRT_JS_EXT_ERRCODE = WRT_MID_ERRCODE + WRT_SET_IDENT(3), + WRT_WM_ERRCODE = WRT_MID_ERRCODE + WRT_SET_IDENT(4), + WRT_PLUGIN_ERRCODE = WRT_MID_ERRCODE + WRT_SET_IDENT(5), + //_ACE support + WRT_SAI_ERRCODE = WRT_MID_ERRCODE + WRT_SET_IDENT(6) +}; + +/** + * WRT error code description + * + * @ WRT_SUCCESS + * There is no error with WRT operations. + * + * @ WRT_ERR_UNKNOW + * An unknow error happened to WRT. + * + * @ WRT_ERR_INVALID_ARG + * Invalid arguments are passed into WRT functions. + * + * @ WRT_ERR_OUT_MEMORY + * No memory space available for WRT. + * + * @ WRT_ERR_NO_DISK_SPACE + * There is no disk space for widget applications. + * + * + * + * + */ +enum WrtError +{ + /* General errors */ + WRT_SUCCESS = WRT_GENERAL_ERRCODE + WRT_ERROR_SET(0x01), + WRT_ERR_UNKNOWN = WRT_GENERAL_ERRCODE + WRT_ERROR_SET(0x02), + WRT_ERR_INVALID_ARG = WRT_GENERAL_ERRCODE + WRT_ERROR_SET(0x03), + WRT_ERR_OUT_OF_MEMORY = WRT_GENERAL_ERRCODE + WRT_ERROR_SET(0x04), + WRT_ERR_NO_DISK_SPACE = WRT_GENERAL_ERRCODE + WRT_ERROR_SET(0x05), + + /* Configuration */ + WRT_CONF_ERR_GCONF_FAILURE = WRT_CONFIG_ERRCODE + WRT_ERROR_SET(0x01), + WRT_CONF_ERR_OBJ_MISSING = WRT_CONFIG_ERRCODE + WRT_ERROR_SET(0x02), + WRT_CONF_ERR_OBJ_EXIST = WRT_CONFIG_ERRCODE + WRT_ERROR_SET(0x03), + WRT_CONF_ERR_START_FILE_MISSING = WRT_CONFIG_ERRCODE + WRT_ERROR_SET(0x04), + WRT_CONF_ERR_EMDB_FAILURE = WRT_CONFIG_ERRCODE + WRT_ERROR_SET(0x05), + WRT_CONF_ERR_EMDB_NO_RECORD = WRT_CONFIG_ERRCODE + WRT_ERROR_SET(0x06), + + /* Domain */ + WRT_DOMAIN_ERR_CREATE_JS_RT = WRT_DOMAIN_ERRCODE + WRT_ERROR_SET(0x01), + WRT_DOMAIN_ERR_MSG_QUEUE = WRT_DOMAIN_ERRCODE + WRT_ERROR_SET(0x02), + + /* Widget manager*/ + WRT_WM_ERR_NOT_INSTALLED = WRT_WM_ERRCODE + WRT_ERROR_SET(0x01), + WRT_WM_ERR_HIGH_VER_INSTALLED = WRT_WM_ERRCODE + WRT_ERROR_SET(0x02), + WRT_WM_ERR_LOW_VER_INSTALLED = WRT_WM_ERRCODE + WRT_ERROR_SET(0x03), + WRT_WM_ERR_INVALID_ARCHIVE = WRT_WM_ERRCODE + WRT_ERROR_SET(0x04), + WRT_WM_ERR_INVALID_CERTIFICATION = WRT_WM_ERRCODE + WRT_ERROR_SET(0x05), + WRT_WM_ERR_NULL_CERTIFICATION = WRT_WM_ERRCODE + WRT_ERROR_SET(0x06), + WRT_WM_ERR_INSTALLATION_CANCEL = WRT_WM_ERRCODE + WRT_ERROR_SET(0x07), + WRT_WM_ERR_ALREADY_INSTALLED = WRT_WM_ERRCODE + WRT_ERROR_SET(0x08), + WRT_WM_ERR_INSTALL_FAILED = WRT_WM_ERRCODE + WRT_ERROR_SET(0x09), + WRT_WM_ERR_DELETE_BY_SERVER = WRT_WM_ERRCODE + WRT_ERROR_SET(0x0a), + WRT_WM_ERR_DEINSTALLATION_CANCEL = WRT_WM_ERRCODE + WRT_ERROR_SET(0x0b), + WRT_WM_ERR_INCORRECT_UPDATE_INFO = WRT_WM_ERRCODE + WRT_ERROR_SET(0x0c), + WRT_WM_ERR_UNREG_FAILED = WRT_WM_ERRCODE + WRT_ERROR_SET(0x0d), + WRT_WM_ERR_REMOVE_FILES_FAILED = WRT_WM_ERRCODE + WRT_ERROR_SET(0x0e), + WRT_WM_ERR_ALREADY_LATEST = WRT_WM_ERRCODE + WRT_ERROR_SET(0x0f), + WRT_WM_ERR_UPDATE_CANCEL = WRT_WM_ERRCODE + WRT_ERROR_SET(0x10), + WRT_WM_ERR_INVALID_APP_ID = WRT_WM_ERRCODE + WRT_ERROR_SET(0x11), + + /* Access Control Manager */ + WRT_SAI_ERR_INIT_ACE_FAILED = WRT_SAI_ERRCODE + WRT_ERROR_SET(0x01) +}; + +namespace CommonError { +enum Type +{ + WrtSuccess, ///< Success + + HandleNotFound, ///< Widget handle was not found + AlreadyRunning, ///< Widget is already running + AlreadyStopped, ///< Widget is already stopped + InvalidLanguage, ///< Widget is invalid in current locales + StillAuthorizing, ///< Widget is still autorizing and has not yet + // finished it + EarlyKilled, ///< Widget was early killed during launch + AccessDenied, ///< Access denied from ACE + CertificateRevoked, ///< Some certificate was revoked. + /// Widget is not allowed to run. + + Unknown ///< Temporary error. Try to not use this. +}; +} +#endif /* _WRT_ERROR_H_ */ + diff --git a/src_wearable/commons/wrt_install_mode.h b/src_wearable/commons/wrt_install_mode.h new file mode 100644 index 0000000..d6462c6 --- /dev/null +++ b/src_wearable/commons/wrt_install_mode.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file wrt_install_mode.h + * @author Jihoon Chung (jihoon.chung@samgsung.com) + * @version + * @brief Definition file of widget install mode class + */ + +#ifndef WRT_INSTALL_MODE_H +#define WRT_INSTALL_MODE_H + +class InstallMode +{ + public: + enum class Command + { + INSTALL, + REINSTALL, + RECOVERY + }; + enum class Location + { + INTERNAL, + EXTERNAL + }; + enum class RootPath + { + RW, + RO + }; + enum class ExtensionType + { + WGT, + DIR + }; + enum class InstallTime + { + NORMAL, + CSC, + PRELOAD, + FOTA, + }; + + InstallMode(Command cmd = Command::INSTALL, + Location lo = Location::INTERNAL, + RootPath root = RootPath::RW, + ExtensionType extensionType = ExtensionType::WGT, + InstallTime time = InstallTime::NORMAL) : + command(cmd), + location(lo), + rootPath(root), + extension(extensionType), + installTime(time), + removable(true) + {}; + + Command command; + Location location; + RootPath rootPath; + ExtensionType extension; + InstallTime installTime; + bool removable; + std::string cscPath; +}; + +#endif // WRT_INSTALL_MODE_H + diff --git a/src_wearable/configuration_parser/deny_all_parser.cpp b/src_wearable/configuration_parser/deny_all_parser.cpp new file mode 100644 index 0000000..e807d5e --- /dev/null +++ b/src_wearable/configuration_parser/deny_all_parser.cpp @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "deny_all_parser.h" +#include + +DenyAllParser::DenyAllParser() : ElementParser() +{} + +ElementParserPtr DenyAllParser::Create() +{ + ThrowMsg(Exception::ParseError, "There must not be any subelement"); +} + +ElementParser::ActionFunc DenyAllParser::GetElementParser(const DPL::String& /*ns*/, + const DPL::String& /*name*/) +{ + ThrowMsg(Exception::ParseError, "There must not be any subelement"); +} + +void DenyAllParser::Accept(const Element& /*element*/) +{ + ThrowMsg(Exception::ParseError, "There must not be any element"); +} + +void DenyAllParser::Accept(const XmlAttribute& /*attribute*/) +{ + ThrowMsg(Exception::ParseError, "There must not be any attribute"); +} + +void DenyAllParser::Accept(const Text& /*text*/) +{ + ThrowMsg(Exception::ParseError, "There must not be any text element"); +} diff --git a/src_wearable/configuration_parser/deny_all_parser.h b/src_wearable/configuration_parser/deny_all_parser.h new file mode 100644 index 0000000..d9dfe56 --- /dev/null +++ b/src_wearable/configuration_parser/deny_all_parser.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file deny_all_parser.h + * @author Lukasz Wrzosek (l.wrzosek@samsung.com) + * @version 0.1 + * @brief + */ +#ifndef DENY_ALL_PARSER_H +#define DENY_ALL_PARSER_H + +#include "element_parser.h" + +struct DenyAllParser : public ElementParser +{ + static ElementParserPtr Create(); + virtual void Accept(const Element& /*element*/); + virtual void Accept(const XmlAttribute& /*attribute*/); + virtual void Accept(const Text& /*text*/); + virtual void Verify() + {} + virtual ActionFunc GetElementParser(const DPL::String& ns, + const DPL::String& name); + + DenyAllParser(); +}; + +#endif // DENY_ALL_PARSER_H diff --git a/src_wearable/configuration_parser/element_parser.h b/src_wearable/configuration_parser/element_parser.h new file mode 100644 index 0000000..c4ea5ba --- /dev/null +++ b/src_wearable/configuration_parser/element_parser.h @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file element_parser.h + * @author Lukasz Wrzosek (l.wrzosek@samsung.com) + * @version 0.1 + * @brief + */ +#ifndef ELEMENT_PARSER_H_ +#define ELEMENT_PARSER_H_ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +struct XmlAttribute +{ + DPL::String prefix; + DPL::String name; + DPL::String value; + DPL::String ns; + DPL::String lang; +}; + +struct Element +{ + DPL::String name; + DPL::String value; + DPL::String ns; + DPL::String lang; +}; + +struct Text +{ + DPL::String value; + DPL::String ns; + DPL::String lang; +}; + +class ElementParser; + +typedef std::shared_ptr ElementParserPtr; + +class ElementParser : public std::enable_shared_from_this +{ + public: + class Exception + { + public: + DECLARE_EXCEPTION_TYPE(DPL::Exception, Base) + DECLARE_EXCEPTION_TYPE(Base, ParseError) + }; + typedef std::function ActionFunc; + typedef std::map FuncMap; + + virtual void Accept(const Element&) = 0; + virtual void Accept(const XmlAttribute&) = 0; + virtual void Accept(const Text&) = 0; + virtual void Verify() = 0; + virtual ActionFunc GetElementParser(const DPL::String &ns, + const DPL::String &name) = 0; + virtual ~ElementParser() + {} + + protected: + ElementParser() + {} +}; + +#endif // ELEMENT_PARSER_H_ diff --git a/src_wearable/configuration_parser/ignoring_parser.cpp b/src_wearable/configuration_parser/ignoring_parser.cpp new file mode 100644 index 0000000..087e6d5 --- /dev/null +++ b/src_wearable/configuration_parser/ignoring_parser.cpp @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file ignoring_parser.cpp + * @author Lukasz Wrzosek (l.wrzosek@samsung.com) + * @version 0.1 + * @brief + */ +#include "ignoring_parser.h" + +#include +#include + +IgnoringParser::IgnoringParser() : ElementParser() +{} + +ElementParserPtr IgnoringParser::Create() +{ + return ElementParserPtr(new IgnoringParser()); +} + +ElementParserPtr IgnoringParser::Reuse() +{ + return shared_from_this(); +} + +ElementParser::ActionFunc IgnoringParser::GetElementParser(const DPL::String& /*ns*/, + const DPL::String& /*name*/) +{ + return std::bind(&IgnoringParser::Reuse, this); +} + +void IgnoringParser::Accept(const Element& /*element*/) +{} + +void IgnoringParser::Accept(const Text& /*text*/) +{} + +void IgnoringParser::Accept(const XmlAttribute& /*attribute*/) +{} + +void IgnoringParser::Verify() +{} diff --git a/src_wearable/configuration_parser/ignoring_parser.h b/src_wearable/configuration_parser/ignoring_parser.h new file mode 100644 index 0000000..b14f1ad --- /dev/null +++ b/src_wearable/configuration_parser/ignoring_parser.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file ignoring_parser.h + * @author Lukasz Wrzosek (l.wrzosek@samsung.com) + * @version 0.1 + * @brief + */ +#ifndef IGNORING_PARSER_H_ +#define IGNORING_PARSER_H_ + +#include "element_parser.h" + +struct IgnoringParser : public ElementParser +{ + static ElementParserPtr Create(); + virtual ActionFunc GetElementParser(const DPL::String& ns, + const DPL::String& name); + virtual void Accept(const Element&); + virtual void Accept(const Text&); + virtual void Accept(const XmlAttribute&); + virtual void Verify(); + + IgnoringParser(); + + private: + ElementParserPtr Reuse(); +}; + +#endif // IGNORING_PARSER_H_ diff --git a/src_wearable/configuration_parser/libiriwrapper.cpp b/src_wearable/configuration_parser/libiriwrapper.cpp new file mode 100644 index 0000000..6d8de2a --- /dev/null +++ b/src_wearable/configuration_parser/libiriwrapper.cpp @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file libiriwrapper.cpp + * @author Piotr Marcinkiewicz (p.marcinkiew@samsung.com + * @version 0.1 + * @brief Libiri parser wrapper + */ +#include +#include +#include "libiriwrapper.h" + +//TODO: Design and implement new IRI manager class + +namespace LibIri { +Wrapper::Wrapper(const char* aIri) : m_Iri(iri_parse(aIri)) +{} +Wrapper::~Wrapper() +{ + iri_destroy(m_Iri); +} +//! \brief Returns true if iri is valid +bool Wrapper::Validate() +{ + return + m_Iri != NULL && + m_Iri->scheme != NULL && ( + m_Iri->display != NULL || + m_Iri->user != NULL || + m_Iri->auth != NULL || + m_Iri->password != NULL || + m_Iri->host != NULL || + m_Iri->path != NULL || + m_Iri->query != NULL || + m_Iri->anchor != NULL || + m_Iri->qparams != NULL || + m_Iri->schemelist != NULL); +} + +std::ostream & operator<<(std::ostream& a_stream, + const Wrapper& a_wrapper) +{ + iri_t& iri = *a_wrapper.m_Iri; +#define PRINT_FIELD(field) "] " #field " [" << (iri.field ? iri.field : "null") + a_stream << + " display [" << (iri.display ? iri.display : "null") << + PRINT_FIELD(scheme) << + PRINT_FIELD(user) << + PRINT_FIELD(auth) << + PRINT_FIELD(password) << + PRINT_FIELD(host) << + "] port [" << (iri.port ? iri.port : -1) << + PRINT_FIELD(path) << + PRINT_FIELD(query) << + PRINT_FIELD(anchor) << + "]"; + return a_stream; +#undef PRINT_FIELD +} +} //namespace LibIri diff --git a/src_wearable/configuration_parser/libiriwrapper.h b/src_wearable/configuration_parser/libiriwrapper.h new file mode 100644 index 0000000..b0b3e86 --- /dev/null +++ b/src_wearable/configuration_parser/libiriwrapper.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file libiriwrapper.cpp + * @author Piotr Marcinkiewicz (p.marcinkiew@samsung.com + * @version 0.1 + * @brief Libiri parser wrapper + */ + +#ifndef _WRT_ENGINE_SRC_INSTALLERCORE_CONFIGURATION_PARSER_LIBIRIWRAPPER_H_ +#define _WRT_ENGINE_SRC_INSTALLERCORE_CONFIGURATION_PARSER_LIBIRIWRAPPER_H_ + +#include +#include + +//TODO: Design and implement new IRI manager class +// +namespace LibIri { +struct Wrapper +{ + Wrapper(const char* aIri); + ~Wrapper(); + iri_t *m_Iri; + //! \brief Returns true if iri is valid + bool Validate(); +}; + +std::ostream & operator<<(std::ostream& a_stream, + const Wrapper& a_wrapper); +} //namespace LibIri + +#endif // _WRT_ENGINE_SRC_INSTALLERCORE_CONFIGURATION_PARSER_LIBIRIWRAPPER_H_ + diff --git a/src_wearable/configuration_parser/parser_runner.cpp b/src_wearable/configuration_parser/parser_runner.cpp new file mode 100644 index 0000000..237d984 --- /dev/null +++ b/src_wearable/configuration_parser/parser_runner.cpp @@ -0,0 +1,463 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file parser_runner.cpp + * @author Lukasz Wrzosek (l.wrzosek@samsung.com) + * @version 0.1 + * @brief + */ +#include "parser_runner.h" +#include "root_parser.h" + +#include "stdio.h" + +#include +#include +#include +#include +#include + +#include + +class ParserRunner::Impl +{ + static void logErrorLibxml2(void *, const char *msg, ...) + { + char buffer[300]; + va_list args; + va_start(args, msg); + vsnprintf(buffer, 300, msg, args); + va_end(args); + _E("%s", buffer); + } + + static void logWarningLibxml2(void *, const char *msg, ...) + { + char buffer[300]; + va_list args; + va_start(args, msg); + vsnprintf(buffer, 300, msg, args); + va_end(args); + _W("%s", buffer); + } + + public: + bool Validate(const std::string& filename, const std::string& schema) + { + int ret = -1; + xmlSchemaParserCtxtPtr ctx; + xmlSchemaValidCtxtPtr vctx; + xmlSchemaPtr xschema; + ctx = xmlSchemaNewParserCtxt(schema.c_str()); + if (ctx == NULL) { + _E("xmlSchemaNewParserCtxt() Failed"); + return false; + } + xschema = xmlSchemaParse(ctx); + if (xschema == NULL) { + _E("xmlSchemaParse() Failed"); + return false; + } + vctx = xmlSchemaNewValidCtxt(xschema); + if (vctx == NULL) { + _E("xmlSchemaNewValidCtxt() Failed"); + return false; + } + xmlSchemaSetValidErrors(vctx, (xmlSchemaValidityErrorFunc)&logErrorLibxml2, (xmlSchemaValidityWarningFunc) &logWarningLibxml2, NULL); + ret = xmlSchemaValidateFile(vctx, filename.c_str(), 0); + if (ret == -1) { + _E("xmlSchemaValidateFile() failed"); + return false; + } else if (ret == 0) { + _E("Config is Valid"); + return true; + } else { + _E("Config Validation Failed with error code %d", ret); + return false; + } + return true; + } + + void Parse(const std::string& filename, + const ElementParserPtr& root) + { + DPL::FileInput input(filename); + Parse(&input, root); + } + + void Parse (DPL::AbstractInput *input, + const ElementParserPtr& root) + { + Try + { + m_reader = xmlReaderForIO(&IoRead, + &IoClose, + input, + NULL, + NULL, + XML_PARSE_NOENT); + + xmlTextReaderSetErrorHandler(m_reader, + &xmlTextReaderErrorHandler, + this); + xmlTextReaderSetStructuredErrorHandler( + m_reader, + &xmlTextReaderStructuredErrorHandler, + this); + SetCurrentElementParser(root); + + while (xmlTextReaderRead(m_reader) == 1) { + switch (xmlTextReaderNodeType(m_reader)) { + case XML_READER_TYPE_END_ELEMENT: + VerifyAndRemoveCurrentElementParser(); + break; + + case XML_READER_TYPE_ELEMENT: + { + // Elements without closing tag don't receive + // XML_READER_TYPE_END_ELEMENT event. + if (IsNoClosingTagElementLeft()) { + VerifyAndRemoveCurrentElementParser(); + } + + DPL::String elementName = GetNameWithoutNamespace(); + DPL::String nameSpace = GetNamespace(); + ElementParserPtr parser = GetCurrentElementParser(); + parser = parser->GetElementParser(nameSpace, + elementName) (); + Assert(!!parser); + SetCurrentElementParser(parser); + ParseNodeElement(parser); + break; + } + case XML_READER_TYPE_TEXT: + case XML_READER_TYPE_CDATA: + { + ParseNodeText(GetCurrentElementParser()); + break; + } + default: + _W("Ignoring Node of Type: %d", xmlTextReaderNodeType(m_reader)); + break; + } + + if (m_parsingError) { + _E("Parsing error occured: %ls", m_errorMsg.c_str()); + ThrowMsg(ElementParser::Exception::ParseError, m_errorMsg); + } + } + + if (m_parsingError) { + _E("Parsing error occured: %ls", m_errorMsg.c_str()); + ThrowMsg(ElementParser::Exception::ParseError, m_errorMsg); + } + + while (!m_stack.empty()) { + VerifyAndRemoveCurrentElementParser(); + } + } + Catch(ElementParser::Exception::Base) + { + CleanupParserRunner(); + _E("%s", _rethrown_exception.DumpToString().c_str()); + ReThrow(ElementParser::Exception::ParseError); + } + CleanupParserRunner(); + } + + Impl() : + m_reader(NULL), + m_parsingError(false) + {} + + ~Impl() + { + CleanupParserRunner(); + } + + private: + typedef std::stack ElementStack; + + private: + static void xmlTextReaderErrorHandler(void* arg, + const char* msg, + xmlParserSeverities /* severity */, + xmlTextReaderLocatorPtr /* locator */) + { + ParserRunner::Impl* impl = static_cast(arg); + impl->ErrorHandler(DPL::FromASCIIString(msg)); + } + + static void xmlTextReaderStructuredErrorHandler(void* arg, + xmlErrorPtr error) + { + ParserRunner::Impl* impl = static_cast(arg); + impl->StructuredErrorHandler(error); + } + + static int XMLCALL IoRead(void *context, + char *buffer, + int len) + { + DPL::AbstractInput *input = static_cast(context); + DPL::BinaryQueueAutoPtr data = input->Read(static_cast(len)); + if (!data.get()) { + return -1; + } + data->Flatten(buffer, data->Size()); + return static_cast(data->Size()); + } + + static int XMLCALL IoClose(void */* context */) + { + // NOOP + return 0; + } + + private: + void SetCurrentElementParser(const ElementParserPtr& elementParser) + { + Assert(elementParser); + + m_stack.push(elementParser); + } + + const ElementParserPtr& GetCurrentElementParser() const + { + Assert(!m_stack.empty()); + + return m_stack.top(); + } + + void VerifyAndRemoveCurrentElementParser() + { + Assert(!m_stack.empty()); + + m_stack.top()->Verify(); + m_stack.pop(); + } + + bool IsNoClosingTagElementLeft() const + { + Assert(m_reader); + + int depth = xmlTextReaderDepth(m_reader); + return (static_cast(m_stack.size()) - 2 == depth); + } + + void ParseNodeElement(const ElementParserPtr& parser) + { + Assert(m_reader); + + Element element; + element.name = GetName(); + element.value = GetValue(); + element.lang = GetLanguageTag(); + element.ns = GetNamespace(); + + _D("value: %ls, lang: %ls, ns: %ls)", + element.value.c_str(), element.lang.c_str(), element.ns.c_str()); + + parser->Accept(element); + ParseNodeElementAttributes(parser); + } + + void ParseNodeElementAttributes(const ElementParserPtr& parser) + { + Assert(m_reader); + int count = xmlTextReaderAttributeCount(m_reader); + for (int i = 0; i < count; ++i) { + xmlTextReaderMoveToAttributeNo(m_reader, i); + + XmlAttribute attribute; + attribute.ns = GetAttributeNamespace(); + attribute.prefix = GetNamePrefix(); + attribute.name = GetNameWithoutNamespace(); + attribute.value = GetValue(); + attribute.lang = GetLanguageTag(); + _D("Attribute name: %ls, value: %ls, prefix: %ls, namespace: %ls, lang: %ls", + attribute.name.c_str(), attribute.value.c_str(), attribute.prefix.c_str(), + attribute.ns.c_str(), attribute.lang.c_str()); + parser->Accept(attribute); + } + } + + void ParseNodeText(const ElementParserPtr& parser) + { + Text text; + text.value = GetValue(); + text.lang = GetLanguageTag(); + parser->Accept(text); + } + + DPL::String GetValue() const + { + DPL::String ret_value; + const xmlChar* value = xmlTextReaderConstValue(m_reader); + if (value) { + ret_value = + DPL::FromUTF8String(reinterpret_cast(value)); + } + + return ret_value; + } + + DPL::String GetAttributeValue(int pos) const + { + DPL::String ret_value; + const xmlChar* value = xmlTextReaderGetAttributeNo(m_reader, pos); + if (value) { + ret_value = + DPL::FromUTF8String(reinterpret_cast(value)); + } + xmlFree(const_cast(value)); + + return ret_value; + } + + DPL::String GetAttributeNamespace() const + { + DPL::String ret_value; + const xmlChar* value = xmlTextReaderLookupNamespace(m_reader, NULL); + if (value) { + ret_value = + DPL::FromUTF8String(reinterpret_cast(value)); + } + xmlFree(const_cast(value)); + + return ret_value; + } + + DPL::String GetName() const + { + DPL::String ret_value; + const xmlChar* value = xmlTextReaderConstName(m_reader); + if (value) { + ret_value = + DPL::FromUTF8String(reinterpret_cast(value)); + } + + return ret_value; + } + + DPL::String GetNamePrefix() const + { + DPL::String ret_value; + const xmlChar* value = xmlTextReaderPrefix(m_reader); + if (value) { + ret_value = + DPL::FromUTF8String(reinterpret_cast(value)); + } + + return ret_value; + } + + DPL::String GetNameWithoutNamespace() const + { + DPL::String ret_value; + const xmlChar* value = xmlTextReaderLocalName(m_reader); + if (value) { + ret_value = + DPL::FromUTF8String(reinterpret_cast(value)); + } + + return ret_value; + } + + DPL::String GetNamespace() const + { + DPL::String ret_value; + + const xmlChar* value = xmlTextReaderConstNamespaceUri(m_reader); + if (value) { + ret_value = + DPL::FromUTF8String(reinterpret_cast(value)); + } + + return ret_value; + } + + DPL::String GetLanguageTag() const + { + DPL::String ret_value; + const xmlChar* value = xmlTextReaderConstXmlLang(m_reader); + if (value) { + ret_value = + DPL::FromUTF8String(reinterpret_cast(value)); + } + + return ret_value; + } + + void ErrorHandler(const DPL::String& msg) + { + _E("LibXML: %ls", msg.c_str()); + m_parsingError = true; + m_errorMsg = m_errorMsg + DPL::FromASCIIString("\n"); + m_errorMsg = m_errorMsg + msg; + } + + void StructuredErrorHandler(xmlErrorPtr error) + { + _E("LibXML: %s", error->message); + m_parsingError = true; + m_errorMsg = m_errorMsg + DPL::FromASCIIString("\n"); + m_errorMsg = m_errorMsg + DPL::FromUTF8String(error->message); + } + + void CleanupParserRunner() + { + while (!m_stack.empty()) { + m_stack.pop(); + } + if (m_reader) { + xmlFreeTextReader(m_reader); + } + m_reader = NULL; + } + + private: + xmlTextReaderPtr m_reader; + ElementStack m_stack; + bool m_parsingError; + DPL::String m_errorMsg; +}; + +ParserRunner::ParserRunner() : + m_impl(new ParserRunner::Impl()) +{} + +bool ParserRunner::Validate(const std::string& filename, const std::string& schema) +{ + return m_impl->Validate(filename, schema); +} + +void ParserRunner::Parse(const std::string& filename, + ElementParserPtr root) +{ + m_impl->Parse(filename, root); +} + +void ParserRunner::Parse(DPL::AbstractInput *input, + ElementParserPtr root) +{ + m_impl->Parse(input, root); +} + +ParserRunner::~ParserRunner() +{ + delete m_impl; +} diff --git a/src_wearable/configuration_parser/parser_runner.h b/src_wearable/configuration_parser/parser_runner.h new file mode 100644 index 0000000..c5c0714 --- /dev/null +++ b/src_wearable/configuration_parser/parser_runner.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file parser_runner.h + * @author Lukasz Wrzosek (l.wrzosek@samsung.com) + * @version 0.1 + * @brief + */ +#ifndef PARSER_RUNNER_H_ +#define PARSER_RUNNER_H_ + +#include +#include +#include +#include "element_parser.h" + +class ParserRunner : private DPL::Noncopyable +{ + public: + bool Validate(const std::string& filename, const std::string& schema); + + void Parse(const std::string& filename, + ElementParserPtr root); + void Parse(DPL::AbstractInput *input, + ElementParserPtr root); + + ParserRunner(); + ~ParserRunner(); + + private: + class Impl; + Impl* m_impl; +}; + +#endif // PARSER_RUNNER_H_ + diff --git a/src_wearable/configuration_parser/root_parser.h b/src_wearable/configuration_parser/root_parser.h new file mode 100755 index 0000000..a54b30d --- /dev/null +++ b/src_wearable/configuration_parser/root_parser.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file root_parser.h + * @author Lukasz Wrzosek (l.wrzosek@samsung.com) + * @version 0.1 + * @brief + */ +#ifndef _WRT_ENGINE_SRC_INSTALLERCORE_CONFIGURATION_PARSER_ROOT_PARSER_H_ +#define _WRT_ENGINE_SRC_INSTALLERCORE_CONFIGURATION_PARSER_ROOT_PARSER_H_ + +#include + +#include "element_parser.h" + +template +class RootParser : public ElementParser +{ + public: + typedef typename ta_Parser::Data Data; + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& name) + { + if (name == m_tag) { + return std::bind(&RootParser::OnWidgetElement, this); + } else { + ThrowMsg(Exception::ParseError, + name << " != " << m_tag); + } + } + + RootParser(Data data, const DPL::String& tag) : + m_data(data), + m_tag(tag) + {} + + virtual ~RootParser() {} + + virtual void Accept(const Element& /*element*/) { } + + virtual void Accept(const XmlAttribute& /*attribute*/) { } + + virtual void Accept(const Text& /*text*/) { } + + virtual void Verify() { } + + private: + + ElementParserPtr OnWidgetElement() + { + typedef ta_Parser Parser; + return ElementParserPtr(new Parser(this->m_data)); + } + + Data m_data; + const DPL::String& m_tag; +}; + +#endif // _WRT_ENGINE_SRC_INSTALLERCORE_CONFIGURATION_PARSER_ROOT_PARSER_H_ diff --git a/src_wearable/configuration_parser/widget_parser.cpp b/src_wearable/configuration_parser/widget_parser.cpp new file mode 100755 index 0000000..db5c3fa --- /dev/null +++ b/src_wearable/configuration_parser/widget_parser.cpp @@ -0,0 +1,3471 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * This file have been implemented in compliance with W3C WARP SPEC. + * but there are some patent issue between W3C WARP SPEC and APPLE. + * so if you want to use this file, refer to the README file in root directory + */ +/** + * @file widget_parser.cpp + * @author Lukasz Wrzosek (l.wrzosek@samsung.com) + * @version 0.1 + * @brief + */ + +#include +#include "ignoring_parser.h" +#include "deny_all_parser.h" +#include +#include "libiriwrapper.h" +#include "wrt-commons/i18n-dao-ro/i18n_dao_read_only.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +using namespace WrtDB; + +namespace Unicode { +static const DPL::String UTF_LRE = L"\x0202a"; +static const DPL::String UTF_LRO = L"\x0202d"; +static const DPL::String UTF_RLE = L"\x0202b"; +static const DPL::String UTF_RLO = L"\x0202e"; +static const DPL::String UTF_PDF = L"\x0202c"; + +Direction ParseDirAttribute(const XmlAttribute& attribute) +{ + Assert(L"dir" == attribute.name); + if (L"ltr" == attribute.value) { + return LRE; + } else if (L"rtl" == attribute.value) { + return RLE; + } else if (L"lro" == attribute.value) { + return LRO; + } else if (L"rlo" == attribute.value) { + return RLO; + } else { + _W("dir attribute has wrong value: %ls ", attribute.value.c_str()); + return EMPTY; + } +} + +void UpdateTextWithDirectionMark(Direction direction, + DPL::String* text) +{ + Assert(text); + switch (direction) { + case RLO: + *text = UTF_RLO + *text + UTF_PDF; + break; + case RLE: + *text = UTF_RLE + *text + UTF_PDF; + break; + case LRE: + *text = UTF_LRE + *text + UTF_PDF; + break; + case LRO: + *text = UTF_LRO + *text + UTF_PDF; + break; + case EMPTY: + break; + default: + Assert(false); + break; + } +} +} // namespace Unicode + +class InnerElementsParser : public ElementParser +{ + public: + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& /*name*/) + { + return std::bind(&InnerElementsParser::Other, this); + } + + virtual void Accept(const Element& /*element*/) + {} + + virtual void Accept(const Text& text) + { + if (!m_text) { + m_text = text; + } else { + m_text->value += text.value; + } + } + + virtual void Accept(const XmlAttribute& attribute) + { + if (attribute.name == L"dir") { + m_textDirection = Unicode::ParseDirAttribute(attribute); + } + } + + virtual void Verify() + { + if (!!m_text) { + Unicode::UpdateTextWithDirectionMark(m_textDirection, + &m_text->value); + m_parentParser->Accept(*m_text); + } + } + + InnerElementsParser(ElementParserPtr parent) : + m_parentParser(parent), + m_textDirection(Unicode::EMPTY) + {} + + ElementParserPtr Other() + { + return ElementParserPtr(new InnerElementsParser( + std::static_pointer_cast( + shared_from_this()))); + } + + private: + boost::optional m_text; + ElementParserPtr m_parentParser; + Unicode::Direction m_textDirection; +}; + +class NameParser : public ElementParser +{ + public: + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& /*name*/) + { + return std::bind(&NameParser::Other, this); + } + + virtual void Accept(const Element& element) + { + m_lang = element.lang; + m_name = L""; + } + + virtual void Accept(const Text& text) + { + if (!m_name) { + m_name = text.value; + } else { + *m_name += text.value; + } + } + + virtual void Accept(const XmlAttribute& attribute) + { + if (attribute.name == L"short") { + if (!m_shortName) { + m_shortName = attribute.value; + } + } else if (attribute.name == L"dir") { + m_textDirection = Unicode::ParseDirAttribute(attribute); + } + } + + virtual void Verify() + { + ConfigParserData::LocalizedData& data = m_data.localizedDataSet[m_lang]; + if (!data.name) { + NormalizeString(m_name); + NormalizeString(m_shortName); + if (!!m_name) { + Unicode::UpdateTextWithDirectionMark(m_textDirection, &*m_name); + } + data.name = m_name; + if (!!m_shortName) { + Unicode::UpdateTextWithDirectionMark(m_textDirection, + &*m_shortName); + } + data.shortName = m_shortName; + } + } + + NameParser(Unicode::Direction direction, + ConfigParserData& data) : + m_data(data), + m_textDirection(direction) + {} + + ElementParserPtr Other() + { + return ElementParserPtr(new InnerElementsParser( + std::static_pointer_cast( + shared_from_this()))); + } + + private: + ConfigParserData& m_data; + DPL::OptionalString m_name; + DPL::OptionalString m_shortName; + DPL::OptionalString m_dir; + DPL::String m_lang; + Unicode::Direction m_textDirection; +}; + +class AccessParser : public ElementParser +{ + public: + enum StandardType + { + STANDARD_TYPE_NONE, + STANDARD_TYPE_WARP + }; + + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& /*name*/) + { + return std::bind(&AccessParser::Other, this); + } + + virtual void Accept(const Element& element) + { + // for tizen web apps WARP should be used + if (element.ns == ConfigurationNamespace::W3CWidgetNamespaceName || + element.ns == ConfigurationNamespace::TizenWebAppNamespaceName) + { + m_standardType = STANDARD_TYPE_WARP; + } + } + + virtual void Accept(const Text& /*text*/) + {} + + void AcceptWac(const XmlAttribute& attribute) + { + if (attribute.name == L"origin") { + m_strIRIOrigin = attribute.value; + NormalizeString(m_strIRIOrigin); + } else if (attribute.name == L"subdomains") { + DPL::String normalizedValue = attribute.value; + NormalizeString(normalizedValue); + + if (normalizedValue == L"true") { + m_bSubDomainAccess = true; + } else if (normalizedValue == L"false") { + m_bSubDomainAccess = false; + } + } + } + + virtual void Accept(const XmlAttribute& attribute) + { + switch (m_standardType) { + case STANDARD_TYPE_WARP: + AcceptWac(attribute); + break; + default: + _E("Error in Access tag - unknown standard."); + break; + } + } + + void VerifyWac() + { + WarpIRI iri; + iri.set(m_strIRIOrigin, false); + + if (!iri.isAccessDefinition()) { + _W("Access list element: %ls is not acceptable by WARP standard and will be ignored!", + m_strIRIOrigin.c_str()); + return; + } + + if(m_strIRIOrigin == L"*") //wildcard match means yes for subdomains + { + m_bSubDomainAccess = true; + } + + ConfigParserData::AccessInfo accessInfo(m_strIRIOrigin, + m_bSubDomainAccess); + //std::pair ret = + m_data.accessInfoSet.insert(accessInfo); + } + + virtual void Verify() + { + switch (m_standardType) { + case STANDARD_TYPE_WARP: + VerifyWac(); + break; + default: + _E("Error in Access tag - unknown standard."); + break; + } + } + + AccessParser(ConfigParserData& data) : + ElementParser(), + m_bSubDomainAccess(false), + m_standardType(STANDARD_TYPE_NONE), + m_network(false), + m_data(data) + {} + + ElementParserPtr Other() + { + return ElementParserPtr(new InnerElementsParser( + ElementParserPtr(shared_from_this()))); + } + + private: + DPL::String m_strIRIOrigin; + bool m_bSubDomainAccess; + StandardType m_standardType; + bool m_network; + ConfigParserData& m_data; +}; + +class DescriptionParser : public ElementParser +{ + public: + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& /*name*/) + { + return std::bind(&DescriptionParser::Other, this); + } + + virtual void Accept(const Element& element) + { + m_lang = element.lang; + m_description = L""; + } + + ElementParserPtr Other() + { + return ElementParserPtr(new InnerElementsParser( + std::static_pointer_cast( + shared_from_this()))); + } + + virtual void Accept(const Text& text) + { + if (!m_description) { + m_description = text.value; + } else { + *m_description += text.value; + } + } + + virtual void Accept(const XmlAttribute& attribute) + { + if (attribute.name == L"dir") { + m_textDirection = Unicode::ParseDirAttribute(attribute); + } + } + + virtual void Verify() + { + ConfigParserData::LocalizedData& data = m_data.localizedDataSet[m_lang]; + if (!data.description) { + if (!!m_description) { + Unicode::UpdateTextWithDirectionMark(m_textDirection, + &*m_description); + } + data.description = m_description; + } + } + + DescriptionParser(Unicode::Direction direction, + ConfigParserData& data) : + m_data(data), + m_lang(), + m_description(), + m_textDirection(direction) + {} + + private: + ConfigParserData& m_data; + DPL::String m_lang; + DPL::OptionalString m_description; + Unicode::Direction m_textDirection; +}; + +class AuthorParser : public ElementParser +{ + public: + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& /*name*/) + { + return std::bind(&AuthorParser::Other, this); + } + + AuthorParser(Unicode::Direction direction, + ConfigParserData& data) : + m_data(data), + m_textDirection(direction) + {} + + virtual void Accept(const Element& /*element*/) + { + m_authorName = L""; + } + + virtual void Accept(const Text& text) + { + *(m_authorName) += text.value; + } + + virtual void Accept(const XmlAttribute& attribute) + { + if (attribute.name == L"href") { + //Validate href IRI and ignore it if invalid + //See also test: ta-argMozRiC-an + LibIri::Wrapper iri(DPL::ToUTF8String(attribute.value).c_str()); + if (iri.Validate()) { + m_authorHref = attribute.value; + } + } else if (attribute.name == L"email") { + m_authorEmail = attribute.value; + } else if (attribute.name == L"dir") { + m_textDirection = Unicode::ParseDirAttribute(attribute); + } + } + + virtual void Verify() + { + if (!m_data.authorName && !m_data.authorHref && !m_data.authorEmail) { + NormalizeString(m_authorName); + NormalizeString(m_authorHref); + NormalizeString(m_authorEmail); + if (!!m_authorName) { + Unicode::UpdateTextWithDirectionMark(m_textDirection, + &*m_authorName); + m_data.authorName = m_authorName; + } + if (!!m_authorHref) { + m_data.authorHref = m_authorHref; + } + if (!!m_authorEmail) { + m_data.authorEmail = m_authorEmail; + } + } + } + + ElementParserPtr Other() + { + return ElementParserPtr(new InnerElementsParser( + std::static_pointer_cast( + shared_from_this()))); + } + + private: + ConfigParserData& m_data; + DPL::OptionalString m_authorEmail; + DPL::OptionalString m_authorHref; + DPL::OptionalString m_authorName; + Unicode::Direction m_textDirection; +}; + +class LicenseParser : public ElementParser +{ + public: + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& /*name*/) + { + return std::bind(&LicenseParser::Other, this); + } + + LicenseParser(Unicode::Direction direction, + ConfigParserData& data) : + m_data(data), + m_ignore(true), + m_textDirection(direction) + {} + + virtual void Accept(const Element& element) + { + if (!m_license) { + m_lang = element.lang; + m_license = L""; + m_ignore = false; + } + } + + virtual void Accept(const Text& text) + { + if (!m_ignore) { + *m_license += text.value; + } + } + + virtual void Accept(const XmlAttribute& attribute) + { + if (!m_ignore) { + if (attribute.name == L"href" && !m_licenseHref) { + m_licenseHref = attribute.value; + } else if (attribute.name == L"file" && !m_licenseFile) { + m_licenseFile = attribute.value; + } else if (attribute.name == L"dir") { + m_textDirection = Unicode::ParseDirAttribute(attribute); + } + } + } + + virtual void Verify() + { + ConfigParserData::LocalizedData& data = m_data.localizedDataSet[m_lang]; + if (!data.license) { + if (!!m_license) { + Unicode::UpdateTextWithDirectionMark(m_textDirection, + &*m_license); + } + data.license = m_license; + data.licenseHref = m_licenseHref; + data.licenseFile = m_licenseFile; + } + } + + ElementParserPtr Other() + { + return ElementParserPtr(new InnerElementsParser( + ElementParserPtr(shared_from_this()))); + } + + private: + ConfigParserData& m_data; + DPL::String m_lang; + bool m_ignore; + + DPL::OptionalString m_license; + DPL::OptionalString m_licenseFile; + DPL::OptionalString m_licenseHref; + Unicode::Direction m_textDirection; +}; + +class IconParser : public ElementParser +{ + DECLARE_EXCEPTION_TYPE(ElementParser::Exception::ParseError, BadSrcError) + + public: + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& /*name*/) + { + return &IgnoringParser::Create; //ignore unknown according to w3c + } + + IconParser(ConfigParserData& data) : ElementParser(), + m_data(data), m_isSmall(false) + {} + + IconParser(ConfigParserData& data, bool isSmall) : ElementParser(), + m_data(data), m_isSmall(isSmall) + {} + + virtual void Accept(const Element& /*element*/) { } + + virtual void Accept(const XmlAttribute& attribute) + { + if (attribute.name == L"src") { + if (attribute.value.size() > 0) { + m_src = attribute.value; + } + } else if (attribute.name == L"width") { + m_width = ParseSizeAttributeValue(attribute.value); + } else if (attribute.name == L"height") { + m_height = ParseSizeAttributeValue(attribute.value); + } + } + + virtual void Accept(const Text& /*text*/) + { + ThrowMsg(Exception::ParseError, "Icon element must be empty"); + } + + virtual void Verify() + { + if (!m_src) { + _W("src attribute of icon element is mandatory - ignoring"); + return; + } + + Try + { + ConfigParserData::Icon icon(delocalizeSrcPath(*m_src)); + icon.width = m_width; + icon.height = m_height; + icon.isSmall = m_isSmall; + + ConfigParserData::IconsList::iterator it = std::find( + m_data.iconsList.begin(), m_data.iconsList.end(), icon); + if (it == m_data.iconsList.end()) { + m_data.iconsList.push_front(icon); + } + } + Catch(BadSrcError) + { + _W("src attribute is invalid: %ls", (*m_src).c_str()); + } + } + + private: + ConfigParserData& m_data; + DPL::OptionalString m_src; + DPL::OptionalInt m_width; + DPL::OptionalInt m_height; + bool m_isSmall; + + static DPL::OptionalInt ParseSizeAttributeValue(const DPL::String& value) + { + DPL::OptionalString normalizedValue = value; + NormalizeString(normalizedValue); + if (!(*normalizedValue).empty()) { + char* reterr = NULL; + errno = 0; + long int valueInt = + strtol(DPL::ToUTF8String(value).c_str(), &reterr, 10); + if (errno != 0 || + std::string(reterr) == DPL::ToUTF8String(value) || + valueInt <= 0) + { + return DPL::OptionalInt(); + } else { + return valueInt; + } + } + return DPL::OptionalInt(); + } + + /** + * @brief delocalizePath removes locales folder from relative path if + * neccessary + * @param source source string + * + * @throw BadSrcError if string is bad value of src attribute + * + * @return corrected string + */ + static DPL::String delocalizeSrcPath(const DPL::String & source) + { + static const DPL::String localeFolder(L"locales/"); + static const int index = localeFolder.size(); + + DPL::String result = source; + + if (source.substr(0, index) == localeFolder) { + size_t pos = result.find_first_of('/', index); + if (pos != std::string::npos && pos + 1 < source.size()) { + result = result.substr(pos + 1, source.size()); + } else { + Throw(BadSrcError); + } + } + return result; + } +}; + +class ContentParser : public ElementParser +{ + public: + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& /*name*/) + { + return &IgnoringParser::Create; //ignore unknown according to w3c + } + + ContentParser(ConfigParserData& data) : + ElementParser(), + m_data(data) + {} + + virtual void Accept(const Element& element) + { + m_namespace = element.ns; + } + + virtual void Accept(const Text& /*text*/) + {} + + virtual void Accept(const XmlAttribute& attribute) + { + DPL::String value = attribute.value; + NormalizeString(value); + + if (attribute.name == L"src") { + m_src = value; + } else if (attribute.name == L"type") { + m_type = value; + MimeTypeUtils::MimeAttributes mimeAttributes = + MimeTypeUtils::getMimeAttributes(value); + if ((mimeAttributes.count(L"charset") > 0) && !m_encoding) + { + m_encoding = mimeAttributes[L"charset"]; + } + } else if (attribute.name == L"encoding") { + if (!value.empty()) { + m_encoding = value; + } + } + } + + virtual void Verify() + { + if(!!m_data.startFileEncountered) + { + if(m_data.startFileNamespace == m_namespace + || m_namespace != ConfigurationNamespace::TizenWebAppNamespaceName) + { + return; + } + //else continue -> if previous item was not in tizen namespace + } + + m_data.startFileEncountered = true; + m_data.startFileNamespace = m_namespace; + + if (m_namespace == ConfigurationNamespace::TizenWebAppNamespaceName && + (!m_src || m_src->empty())) { + ThrowMsg(Exception::ParseError, "content element must have correct src element"); + } + + if (!!m_src) { + m_data.startFile = m_src; + m_data.startFileContentType = m_type; + if (!!m_encoding) { + m_data.startFileEncoding = m_encoding; + } else { + m_data.startFileEncoding = L"UTF-8"; + } + } + } + + private: + DPL::OptionalString m_src; + DPL::OptionalString m_type; + DPL::OptionalString m_encoding; + ConfigParserData& m_data; + DPL::String m_namespace; +}; + +class PreferenceParser : public ElementParser +{ + public: + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& /*name*/) + { + return &IgnoringParser::Create; //ignore unknown according to w3c + } + + virtual void Accept(const XmlAttribute& attribute) + { + if (attribute.name == L"name") { + m_name = attribute.value; + } else if (attribute.name == L"value") { + m_value = attribute.value; + } else if (attribute.name == L"readonly") { + if (attribute.value == L"true") { + m_required = true; + } else { + m_required = false; + } + } + } + + virtual void Accept(const Element& /*element*/) + {} + + virtual void Accept(const Text& /*text*/) + { + ThrowMsg(Exception::ParseError, "param element must be empty"); + } + + virtual void Verify() + { + if (!m_name) { + _W("preference element must have name attribute"); + return; + } + NormalizeString(m_name); + NormalizeString(m_value); + ConfigParserData::Preference preference(*m_name, m_required); + preference.value = m_value; + if (m_data.preferencesList.find(preference) == + m_data.preferencesList.end()) + { + m_data.preferencesList.insert(preference); + } + } + + PreferenceParser(ConfigParserData& data) : + ElementParser(), + m_required(false), + m_data(data) + {} + + private: + DPL::OptionalString m_name; + DPL::OptionalString m_value; + bool m_required; + ConfigParserData& m_data; +}; + +class SettingParser : public ElementParser +{ + public: + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& /*name*/) + { + return &IgnoringParser::Create; //ignore unknown according to w3c + } + + virtual void Accept(const Text& /*text*/) + {} + + virtual void Accept(const Element& /*element*/) + {} + + virtual void Accept(const XmlAttribute& attribute) + { + m_setting.m_name = attribute.name; + m_setting.m_value = attribute.value; + m_data.settingsList.insert(m_setting); + } + + virtual void Verify() + {} + + SettingParser(ConfigParserData& data) : + ElementParser(), + m_data(data), + m_setting(L"", L"") + {} + + private: + ConfigParserData& m_data; + ConfigParserData::Setting m_setting; +}; + +class AppControlParser : public ElementParser +{ + public: + struct SourceParser : public ElementParser + { + public: + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& /*name*/) + { + return &IgnoringParser::Create; //ignore unknown according to w3c + } + + virtual void Accept(const Text& /*text*/) + {} + + virtual void Accept(const Element& /*element*/) + {} + + virtual void Accept(const XmlAttribute& attribute) + { + if (attribute.name == L"name") { + if (attribute.value.size() > 0) { + m_value = attribute.value; + NormalizeString(m_value); + } + } + } + + virtual void Verify() + { + if (!m_value || *m_value == L"") { + return; + } + + m_data.m_src = *m_value; + } + + SourceParser(ConfigParserData::AppControlInfo& data) : + ElementParser(), + m_properNamespace(false), + m_data(data) + {} + + private: + bool m_properNamespace; + DPL::OptionalString m_value; + ConfigParserData::AppControlInfo& m_data; + }; + + struct OperationParser : public ElementParser + { + public: + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& /*name*/) + { + return &IgnoringParser::Create; //ignore unknown according to w3c + } + + virtual void Accept(const Text& /*text*/) + {} + + virtual void Accept(const Element& /*element*/) + {} + + virtual void Accept(const XmlAttribute& attribute) + { + if (attribute.name == L"name") { + if (attribute.value.size() > 0) { + m_value = attribute.value; + NormalizeString(m_value); + } + } + } + + virtual void Verify() + { + if (!m_value || *m_value == L"") { + return; + } + + m_data.m_operation = *m_value; + } + + OperationParser(ConfigParserData::AppControlInfo& data) : + ElementParser(), + m_properNamespace(false), + m_data(data) + {} + + private: + bool m_properNamespace; + DPL::OptionalString m_value; + ConfigParserData::AppControlInfo& m_data; + }; + + struct UriParser : public ElementParser + { + public: + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& /*name*/) + { + return &IgnoringParser::Create; //ignore unknown according to w3c + } + + virtual void Accept(const Text& /*text*/) + {} + + virtual void Accept(const Element& /*element*/) + {} + + virtual void Accept(const XmlAttribute& attribute) + { + if (attribute.name == L"name") { + if (attribute.value.size() > 0) { + m_value = attribute.value; + NormalizeString(m_value); + } + } + } + + virtual void Verify() + { + // exception + DPL::String ignoreUri(L"file"); + + if (!!m_value && *m_value == ignoreUri) + { + _D("exception : '%ls' scheme will be ignored.", (*m_value).c_str()); + m_value = DPL::OptionalString(); + } + + if (!m_value || *m_value == L"") { + return; + } + + DPL::String wildString(L"*/*"); + if ((m_data.m_uriList.find(wildString) == m_data.m_uriList.end()) + && (m_data.m_uriList.find(*m_value) == m_data.m_uriList.end())) + { + m_data.m_uriList.insert(*m_value); + } else { + _D("Ignoring uri with name %ls", (*m_value).c_str()); + } + } + + UriParser(ConfigParserData::AppControlInfo& data) : + ElementParser(), + m_properNamespace(false), + m_data(data) + {} + + private: + bool m_properNamespace; + DPL::OptionalString m_value; + ConfigParserData::AppControlInfo& m_data; + }; + + struct MimeParser : public ElementParser + { + public: + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& /*name*/) + { + return &IgnoringParser::Create; //ignore unknown according to w3c + } + + virtual void Accept(const Text& /*text*/) + {} + + virtual void Accept(const Element& /*element*/) + {} + + virtual void Accept(const XmlAttribute& attribute) + { + if (attribute.name == L"name") { + if (attribute.value.size() > 0) { + m_value = attribute.value; + NormalizeString(m_value); + } + } + } + + virtual void Verify() + { + if (!m_value || *m_value == L"") { + return; + } + + DPL::String wildString(L"*/*"); + if ((m_data.m_mimeList.find(wildString) == + m_data.m_mimeList.end()) + && (m_data.m_mimeList.find(*m_value) == + m_data.m_mimeList.end())) + { + m_data.m_mimeList.insert(*m_value); + } else { + _D("Ignoring mime with name %ls", (*m_value).c_str()); + } + } + + MimeParser(ConfigParserData::AppControlInfo& data) : + ElementParser(), + m_properNamespace(false), + m_data(data) + {} + + private: + bool m_properNamespace; + DPL::OptionalString m_value; + ConfigParserData::AppControlInfo& m_data; + }; + + struct DispositionParser : public ElementParser + { + public: + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& /*name*/) + { + return &IgnoringParser::Create; + } + + virtual void Accept(const Text& /*text*/) + {} + + virtual void Accept(const Element& /*element*/) + {} + + virtual void Accept(const XmlAttribute& attribute) + { + if (attribute.name == L"name") { + if (attribute.value.size() > 0) { + m_value = attribute.value; + NormalizeString(m_value); + } + } + } + + virtual void Verify() + { + if (!m_value || *m_value == L"") { + return; + } + + DPL::String windowString(L"window"); + DPL::String inlineString(L"inline"); + + if (*m_value == L"window") { + m_data.m_disposition = + ConfigParserData::AppControlInfo::Disposition::WINDOW; + } else if (*m_value == L"inline") { + m_data.m_disposition = + ConfigParserData::AppControlInfo::Disposition::INLINE; + } else { + _D("Ignoring dispostion value %ls", (*m_value).c_str()); + } + } + + DispositionParser(ConfigParserData::AppControlInfo& data) : + ElementParser(), + m_properNamespace(false), + m_data(data) + {} + + private: + bool m_properNamespace; + DPL::OptionalString m_value; + ConfigParserData::AppControlInfo& m_data; + }; + + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& name) + { + if (name == L"src") { + return std::bind(&AppControlParser::OnSourceElement, this); + } else if (name == L"operation") { + return std::bind(&AppControlParser::OnOperationElement, this); + } else if (name == L"uri") { + return std::bind(&AppControlParser::OnUriElement, this); + } else if (name == L"mime") { + return std::bind(&AppControlParser::OnMimeElement, this); + } else if (name == L"disposition") { + return std::bind(&AppControlParser::OnDispositionElement, this); + } else { + return &IgnoringParser::Create; //ignore unknown according to w3c + } + } + + virtual void Accept(const XmlAttribute& /*attribute*/) + {} + + virtual void Accept(const Element& element) + { + _W("namespace for app service = %ls", element.ns.c_str()); + if (element.ns == ConfigurationNamespace::W3CWidgetNamespaceName) { + ThrowMsg(Exception::ParseError, + "Wrong xml namespace for widget element"); + } + } + + virtual void Accept(const Text& /*text*/) + { + ThrowMsg(Exception::ParseError, "param element must be empty"); + } + + virtual void Verify() + { + if (m_appControl.m_src == L"") { + ThrowMsg(Exception::ParseError, "service element must have src element"); + } + + if (m_appControl.m_operation == L"") { + ThrowMsg(Exception::ParseError, "service element must have operation element"); + } + + auto res = std::find(m_data.appControlList.begin(), m_data.appControlList.end(), m_appControl); + if(res != m_data.appControlList.end()) { + ThrowMsg(Exception::ParseError, "service element must be unique"); + } + +#ifdef NFC_EXCEPTION_HANDLING_FOR_TIZEN_2_2_ONLY + // XXX This feature should be retained to Tizen 2.2 only. + // NFC exception handling which was requested from Tizen Device API team. + + const DPL::String exceptionNfcOperation = + L"http://tizen.org/appcontrol/operation/nfc/transaction"; + const DPL::String exceptionNfcUri = L"nfc://secure/aid/"; + const DPL::String divertingNfcUri1 = L"nfc://secure/SIM1/aid/"; + const DPL::String divertingNfcUri2 = L"nfc://secure/eSE/aid/"; + + if (m_appControl.m_operation == exceptionNfcOperation + && m_appControl.m_mimeList.empty() + && m_appControl.m_uriList.size() == 1 + && (m_appControl.m_uriList.begin())->compare(0, exceptionNfcUri.length(), exceptionNfcUri) == 0) + { + DPL::String originalUri = *m_appControl.m_uriList.begin(); + DPL::String newUri = originalUri; + + newUri.replace(0, exceptionNfcUri.length(), divertingNfcUri1); + m_appControl.m_uriList.erase(m_appControl.m_uriList.begin()); + m_appControl.m_uriList.insert(newUri); + m_data.appControlList.push_back(m_appControl); + _D("NFC exception : %ls -> %ls", originalUri.c_str(), newUri.c_str()); + + newUri = originalUri; + newUri.replace(0, exceptionNfcUri.length(), divertingNfcUri2); + m_appControl.m_uriList.erase(m_appControl.m_uriList.begin()); + m_appControl.m_uriList.insert(newUri); + m_data.appControlList.push_back(m_appControl); + _D("NFC exception : %ls -> %ls", originalUri.c_str(), newUri.c_str()); + + return; + } +#endif // NFC_EXCEPTION_HANDLING_FOR_TIZEN_2_2_ONLY + + m_data.appControlList.push_back(m_appControl); + } + + ElementParserPtr OnSourceElement() + { + return ElementParserPtr(new SourceParser(m_appControl)); + } + + ElementParserPtr OnOperationElement() + { + return ElementParserPtr(new OperationParser(m_appControl)); + } + + ElementParserPtr OnUriElement() + { + return ElementParserPtr(new UriParser(m_appControl)); + } + + ElementParserPtr OnMimeElement() + { + return ElementParserPtr(new MimeParser(m_appControl)); + } + + ElementParserPtr OnDispositionElement() + { + return ElementParserPtr(new DispositionParser(m_appControl)); + } + + AppControlParser(ConfigParserData& data) : + ElementParser(), + m_data(data), + m_appControl(L"") + {} + + private: + ConfigParserData& m_data; + ConfigParserData::AppControlInfo m_appControl; +}; + +class ApplicationParser : public ElementParser +{ + public: + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& /*name*/) + { + return &IgnoringParser::Create; //ignore unknown according to w3c + } + + virtual void Accept(const Text& /*text*/) + { + if (m_properNamespace) { + ThrowMsg(Exception::ParseError, "application element must be empty"); + } + } + + virtual void Accept(const Element& element) + { + if (element.ns == + ConfigurationNamespace::TizenWebAppNamespaceName) + { + m_properNamespace = true; + } + } + + virtual void Accept(const XmlAttribute& attribute) + { + if (m_properNamespace) { + if (attribute.name == L"id") { + m_id = attribute.value; + NormalizeAndTrimSpaceString(m_id); + } else if (attribute.name == L"package") { + m_package = attribute.value; + } else if (attribute.name == L"required_version") { + m_version = attribute.value; + NormalizeString(m_version); + } else { + ThrowMsg(Exception::ParseError, + "unknown attribute '" + + DPL::ToUTF8String(attribute.name) + + "' in application element"); + } + } + } + + virtual void Verify() + { + if(m_data.didFoundTizenApplicationElement) + { + ThrowMsg(Exception::ParseError, "tizen:application element must occur only once"); + } + m_data.didFoundTizenApplicationElement = true; + + VerifyIdAndPackage(); + VerifyVersion(); + } + + ApplicationParser(ConfigParserData& data) : + ElementParser(), + m_data(data), + m_id(DPL::OptionalString()), + m_version(DPL::OptionalString()), + m_properNamespace(false) + {} + + static const char* const REGEXP_ID; + + private: + void VerifyIdAndPackage() + { + if (!m_package) + { + ThrowMsg(Exception::ParseError, + "application element must have package attribute"); + } + else + { + pcrecpp::RE re(REGEXP_PACKAGE); + if (!re.FullMatch(DPL::ToUTF8String(*m_package))) + { + ThrowMsg(Exception::ParseError, + "invalid format of package attribute"); + } + } + + if (!m_id) { + ThrowMsg(Exception::ParseError, + "application element must have id attribute"); + } + else + { + std::string package; + pcrecpp::RE re(REGEXP_ID); + if (!re.FullMatch(DPL::ToUTF8String(*m_id), &package)) + { + ThrowMsg(Exception::ParseError, + "invalid format of id attribute"); + } + if (package != DPL::ToUTF8String(*m_package)) + { + ThrowMsg(Exception::ParseError, + "invalid package prefix in id attribute"); + } + } + + m_data.tizenAppId = m_id; + m_data.tizenPkgId = m_package; + } + + void VerifyVersion() + { + if (!m_version) + { + ThrowMsg(Exception::ParseError, + "application element must have required_version attribute"); + } + else + { + pcrecpp::RE re(REGEXP_VERSION); + if (!re.FullMatch(DPL::ToUTF8String(*m_version))) + { + ThrowMsg(Exception::ParseError, + "invalid format of version attribute"); + } + } + + m_data.tizenMinVersionRequired = m_version; + } + + static const char* const REGEXP_PACKAGE; + static const char* const REGEXP_VERSION; + + ConfigParserData& m_data; + DPL::OptionalString m_id; + DPL::OptionalString m_package; + DPL::OptionalString m_version; + bool m_properNamespace; +}; + +const char* const ApplicationParser::REGEXP_PACKAGE = "[0-9A-Za-z]{10}"; +const char* const ApplicationParser::REGEXP_ID = "([0-9A-Za-z]{10})\\.[0-9A-Za-z]{1,52}"; +const char* const ApplicationParser::REGEXP_VERSION = "\\d+\\.\\d+(\\.\\d+)*"; + +class SplashParser : public ElementParser +{ + public: + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& /*name*/) + { + return &IgnoringParser::Create; //ignore unknown according to w3c + } + + virtual void Accept(const XmlAttribute& attribute) + { + if (m_properNamespace) + { + if (attribute.name == L"src") { + if (attribute.value.size() > 0) { + m_src = attribute.value; + } + } + } + } + + virtual void Accept(const Element& element) + { + if (element.ns == + ConfigurationNamespace::TizenWebAppNamespaceName) + { + m_properNamespace = true; + } + } + + virtual void Accept(const Text& /*text*/) + {} + + virtual void Verify() + { + if (!m_src) + { + _W("src attribute of splash element is mandatory - ignoring"); + return; + } + + m_data.splashImgSrc = m_src; + } + + SplashParser(ConfigParserData& data) : + ElementParser(), + m_data(data), + m_properNamespace(false) + {} + + private: + DPL::OptionalString m_src; + ConfigParserData& m_data; + bool m_properNamespace; +}; + +class BackgroundParser : public ElementParser +{ + public: + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& /*name*/) + { + return &IgnoringParser::Create; //ignore unknown according to w3c + } + + virtual void Accept(const XmlAttribute& attribute) + { + if (attribute.name == L"src") { + if (attribute.value.size() > 0) { + m_src = attribute.value; + } + } + } + + virtual void Accept(const Element& /*element*/) + {} + + virtual void Accept(const Text& /*text*/) + {} + + virtual void Verify() + { + if (!m_src) { + _W("src attribute of background element is mandatory - ignoring"); + return; + } + + m_data.backgroundPage = m_src; + } + + explicit BackgroundParser(ConfigParserData& data) : + m_data(data) + {} + + private: + DPL::OptionalString m_src; + ConfigParserData& m_data; +}; + +class PrivilegeParser : public ElementParser +{ + public: + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& /*name*/) + { + return &IgnoringParser::Create; //ignore unknown according to w3c + } + + virtual void Accept(const Text& /*text*/) + {} + + virtual void Accept(const Element& element) + { + if (element.ns == + ConfigurationNamespace::TizenWebAppNamespaceName) + { + m_properNamespace = true; + } + _D("element"); + } + + virtual void Accept(const XmlAttribute& attribute) + { + if (m_properNamespace) { + if (attribute.name == L"name") { + m_feature.name = attribute.value; + m_privilege.name = attribute.value; + } + } + } + + virtual void Verify() + { + LibIri::Wrapper iri(DPL::ToUTF8String(m_feature.name).c_str()); + + if (m_feature.name != L"") { + if (iri.Validate()) { + if (m_data.featuresList.find(m_feature) == + m_data.featuresList.end()) + { + m_data.featuresList.insert(m_feature); + } else { + _D("Ignoring feature with name %ls", m_feature.name.c_str()); + } + } + } + + LibIri::Wrapper iriPrivilege( + DPL::ToUTF8String(m_privilege.name).c_str()); + + if (m_privilege.name != L"") { + if (iriPrivilege.Validate()) { + if (m_data.privilegeList.find(m_privilege) == + m_data.privilegeList.end()) + { + m_data.privilegeList.insert(m_privilege); + } else { + _D("Ignoring privilege with name %ls", m_privilege.name.c_str()); + } + } + } + } + + PrivilegeParser(ConfigParserData& data) : + ElementParser(), + m_data(data), + m_feature(L""), + m_privilege(L""), + m_properNamespace(false) + {} + + private: + ConfigParserData& m_data; + ConfigParserData::Feature m_feature; + ConfigParserData::Privilege m_privilege; + bool m_properNamespace; +}; + +class CategoryParser : public ElementParser +{ + public: + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& /*name*/) + { + return &IgnoringParser::Create; //ignore unknown according to w3c + } + + virtual void Accept(const Element& element) + { + if (element.ns == + ConfigurationNamespace::TizenWebAppNamespaceName) + { + m_properNamespace = true; + } + LogDebug("element"); + } + + virtual void Accept(const XmlAttribute& attribute) + { + if (m_properNamespace) { + if (attribute.name == L"name") { + if (attribute.value.size() > 0) { + m_name = attribute.value; + } + } + } + } + + virtual void Accept(const Text& /*text*/) + {} + + virtual void Verify() + { + if (!m_name) { + _W("name attribute of category element is mandatory - ignoring"); + return; + } + + if (m_data.categoryList.find(*m_name) == + m_data.categoryList.end()) + { + m_data.categoryList.insert(*m_name); + } + + } + + explicit CategoryParser(ConfigParserData& data) : + m_data(data), + m_properNamespace(false) + {} + + private: + DPL::OptionalString m_name; + ConfigParserData& m_data; + bool m_properNamespace; +}; + +#ifdef DBOX_ENABLED +class AppWidgetParser : public ElementParser +{ + public: + + struct BoxLabelParser : public ElementParser + { + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& /*name*/) + { + return &IgnoringParser::Create; //ignore unknown according to w3c + } + + virtual void Accept(const XmlAttribute& attribute) + { + if (m_properNamespace) { + m_lang = attribute.lang; + } + } + virtual void Accept(const Element& element) + { + if (element.ns == + ConfigurationNamespace::TizenWebAppNamespaceName) + { + m_properNamespace = true; + } + } + + virtual void Accept(const Text& text) + { + if (m_properNamespace) { + m_label = text.value; + } + } + + virtual void Verify() + { + std::pair boxLabel; + if (m_label.empty()) { + _W("box-label element is empty"); + boxLabel.first = DPL::FromUTF8String(""); + boxLabel.second = DPL::FromUTF8String(""); + m_data.m_label.push_back(boxLabel); + } + else { + boxLabel.first = m_lang; + boxLabel.second = m_label; + m_data.m_label.push_back(boxLabel); + } + } + + BoxLabelParser(ConfigParserData::LiveboxInfo& data) : + ElementParser(), + m_properNamespace(false), + m_data(data) + {} + + private: + DPL::String m_lang; + DPL::String m_label; + bool m_properNamespace; + ConfigParserData::LiveboxInfo& m_data; + }; + + struct BoxIconParser : public ElementParser + { + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& /*name*/) + { + return &IgnoringParser::Create; //ignore unknown according to w3c + } + + virtual void Accept(const XmlAttribute& attribute) + { + if (m_properNamespace) { + if (attribute.name == L"src") { + m_icon = attribute.value; + } + } + } + + virtual void Accept(const Element& element) + { + if (element.ns == + ConfigurationNamespace::TizenWebAppNamespaceName) + { + m_properNamespace = true; + } + } + + virtual void Accept(const Text& /*text*/) + {} + + virtual void Verify() + { + if (m_icon.empty()) { + ThrowMsg(Exception::ParseError, + "src attribute of box-icon element is mandatory - ignoring"); + } + if (!m_data.m_icon.empty()) { + ThrowMsg(Exception::ParseError, + " element should occur as 0 or 1 time"); + } + m_data.m_icon = m_icon; + } + + explicit BoxIconParser(ConfigParserData::LiveboxInfo& data) : + ElementParser(), + m_properNamespace(false), + m_data(data) + {} + + private: + DPL::String m_icon; + bool m_properNamespace; + ConfigParserData::LiveboxInfo& m_data; + }; + + struct BoxContentParser : public ElementParser + { + struct BoxSizeParser : public ElementParser + { + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& /*name*/) + { + return &IgnoringParser::Create; //ignore unknown according to w3c + } + + virtual void Accept(const XmlAttribute& attribute) + { + if (m_properNamespace) { + if (attribute.name == L"preview") { + m_preview = attribute.value; + } + if (attribute.name == L"use-decoration") { + m_useDecoration = attribute.value; + } + } + } + + virtual void Accept(const Element& element) + { + if (element.ns == + ConfigurationNamespace::TizenWebAppNamespaceName) + { + m_properNamespace = true; + } + } + + virtual void Accept(const Text& text) + { + if (m_properNamespace) { + m_size = text.value; + } + } + + virtual void Verify() + { + if(m_size.empty()) { + ThrowMsg(Exception::ParseError, + "size is mandatory - ignoring"); + } + + if (m_useDecoration.empty() || CheckIfNotTrueNorFalse(m_useDecoration)) { + m_useDecoration = L"true"; // default value + } + + ConfigParserData::LiveboxInfo::BoxSizeInfo boxSizeInfo; + boxSizeInfo.m_size = m_size; + boxSizeInfo.m_preview = m_preview; + boxSizeInfo.m_useDecoration = m_useDecoration; + m_data.m_boxSize.push_back(boxSizeInfo); + } + + explicit BoxSizeParser( + ConfigParserData::LiveboxInfo::BoxContentInfo& data) : + ElementParser(), + m_properNamespace(false), + m_data(data) + {} + + private: + DPL::String m_size; + DPL::String m_preview; + DPL::String m_useDecoration; + bool m_properNamespace; + ConfigParserData::LiveboxInfo::BoxContentInfo& m_data; + }; + + struct PdParser : public ElementParser + { + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& /*name*/) + { + return &IgnoringParser::Create; //ignore unknown according to w3c + } + + virtual void Accept(const XmlAttribute& attribute) + { + if (m_properNamespace) { + if (attribute.name == L"src") { + m_src = attribute.value; + } else if (attribute.name == L"width") { + m_width = attribute.value; + } else if (attribute.name == L"height") { + m_height = attribute.value; + } else if (attribute.name == L"fast-open") { + m_fastOpen= attribute.value; + } + } + } + + virtual void Accept(const Element& element) + { + if (element.ns == + ConfigurationNamespace::TizenWebAppNamespaceName) + { + m_properNamespace = true; + } + } + + virtual void Accept(const Text& /*text*/) + {} + + virtual void Verify() + { + if (m_src.empty()) { + ThrowMsg(Exception::ParseError, + "src attribute of pd element is mandatory - ignoring"); + } + + if (m_width.empty()) { + ThrowMsg(Exception::ParseError, + "width attribute of pd element is mandatory - ignoring"); + } + + if (m_height.empty()) { + ThrowMsg(Exception::ParseError, + "height attribute of pd element is mandatory - ignoring"); + } + + if (!ConvertToInt(m_width)) { + ThrowMsg(Exception::ParseError, + "width attribute of pd element cannot be converted to int - ignoring. value: " << m_width); + } + + + DPL::OptionalInt height = ConvertToInt(m_height); + + if (!height) { + ThrowMsg(Exception::ParseError, + "height attribute of pd element cannot be converted to int - ignoring. value: " << m_height); + } + + if (*height < 1) { + m_height = L"1"; + _D("height attribute of pd element shouldn't be less than 1. Changed to 1 from %d", *height); + } else if (*height > 380){ + m_height = L"380"; + _D("height attribute of pd element shouldn't be greater than 380. Changed to 380 from %d", *height); + } + + if (!m_data.m_pdSrc.empty()) { + ThrowMsg(Exception::ParseError, " element should occur as 0 or 1 time"); + } + + m_data.m_pdSrc = m_src; + m_data.m_pdWidth = m_width; + m_data.m_pdHeight = m_height; + m_data.m_pdFastOpen = m_fastOpen; + } + + explicit PdParser( + ConfigParserData::LiveboxInfo::BoxContentInfo& data) : + ElementParser(), + m_properNamespace(false), + m_data(data) + {} + + private: + DPL::OptionalInt ConvertToInt(const DPL::String& intAsString) + { + char * endptr; + std::string tempStr = DPL::ToUTF8String(intAsString); + const char * intAsString_c = tempStr.c_str(); + errno = 0; + long int intAsString_i = strtol(intAsString_c, &endptr, 10); + + if ((errno == ERANGE && (intAsString_i == LONG_MAX || intAsString_i == LONG_MIN)) + || intAsString_i > INT_MAX || intAsString_i < INT_MIN + || *endptr != '\0') { + return DPL::OptionalInt(); + } + + return static_cast(intAsString_i); + } + + DPL::String m_src; + DPL::String m_width; + DPL::String m_height; + DPL::String m_fastOpen; + + bool m_properNamespace; + ConfigParserData::LiveboxInfo::BoxContentInfo& m_data; + }; + + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& name) + { + if (name == L"box-size") { + return std::bind(&AppWidgetParser::BoxContentParser::OnBoxSizeElement, this); + } else if (name == L"pd") { + return std::bind(&AppWidgetParser::BoxContentParser::OnPdElement, this); + } else { + ThrowMsg(Exception::ParseError, + "No element parser for name: " << name); + } + } + + virtual void Accept(const XmlAttribute& attribute) + { + if (m_properNamespace) { + if (attribute.name == L"src") { + m_box.m_boxSrc = attribute.value; + } + if (attribute.name == L"mouse-event") { + m_box.m_boxMouseEvent = attribute.value; + } + if (attribute.name == L"touch-effect") { + m_box.m_boxTouchEffect = attribute.value; + } + } + } + + virtual void Accept(const Element& element) + { + if (element.ns == + ConfigurationNamespace::TizenWebAppNamespaceName) + { + m_properNamespace = true; + } + } + + virtual void Accept(const Text& /*text*/) + {} + + virtual void Verify() + { + if (m_box.m_boxSrc.empty()) { + ThrowMsg(Exception::ParseError, + "src attribute of box-content element is mandatory - ignoring"); + } + + if (m_box.m_boxMouseEvent.empty() || CheckIfNotTrueNorFalse(m_box.m_boxMouseEvent)) { + m_box.m_boxMouseEvent = L"false"; // default value + } + + if (m_box.m_boxTouchEffect.empty() || CheckIfNotTrueNorFalse(m_box.m_boxTouchEffect)) { + m_box.m_boxTouchEffect = L"true"; // default value + } + + if (m_box.m_boxSize.empty()) { + ThrowMsg(Exception::ParseError, + "box-size element of box-content element not found - ignoring"); + } + + if (!m_data.m_boxInfo.m_boxSrc.empty()) { + ThrowMsg(Exception::ParseError, " element must occur exactly 1 time"); + } + + m_data.m_boxInfo = m_box; + } + + explicit BoxContentParser(ConfigParserData::LiveboxInfo& data) : + ElementParser(), + m_properNamespace(false), + m_data(data) + {} + + ElementParserPtr OnBoxSizeElement() + { + return ElementParserPtr(new BoxSizeParser(m_box)); + } + + ElementParserPtr OnPdElement() + { + return ElementParserPtr(new PdParser(m_box)); + } + + private: + bool m_properNamespace; + ConfigParserData::LiveboxInfo& m_data; + ConfigParserData::LiveboxInfo::BoxContentInfo m_box; + }; + + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& name) + { + if (name == L"box-label") { + return std::bind(&AppWidgetParser::OnBoxLabelElement, this); + } else if (name == L"box-icon") { + return std::bind(&AppWidgetParser::OnBoxIconElement, this); + } else if (name == L"box-content") { + return std::bind(&AppWidgetParser::OnBoxContentElement, this); + } else { + return &IgnoringParser::Create; //ignore unknown according to w3c + } + } + + virtual void Accept(const XmlAttribute& attribute) + { + if (m_properNamespace) { + if (attribute.name == L"id") { + m_liveboxId = attribute.value; + } else if (attribute.name == L"primary") { + m_primary = attribute.value; + } else if (attribute.name == L"auto-launch") { + m_autoLaunch = attribute.value; + } else if (attribute.name == L"update-period") { + m_updatePeriod = attribute.value; + } else if (attribute.name == L"type") { + m_type = attribute.value; + } + } + } + + virtual void Accept(const Element& element) + { + if (element.ns == + ConfigurationNamespace::TizenWebAppNamespaceName) + { + m_properNamespace = true; + } + } + + virtual void Accept(const Text& /*text*/) + {} + + virtual void Verify() + { + if (m_liveboxId.empty()) { + ThrowMsg(Exception::ParseError, + "app-widget element must have id attribute"); + } + else + { + pcrecpp::RE re(REGEXP_ID_STRING.c_str()); + if (!re.FullMatch(DPL::ToUTF8String(m_liveboxId))) + { + ThrowMsg(Exception::ParseError, + "invalid format of app-widget id attribute"); + } + } + + if (m_primary.empty() || CheckIfNotTrueNorFalse(m_primary)) + { + m_primary = L"true"; //default value + } + + if (!m_updatePeriod.empty()) + { + char * endptr; + errno = 0; + std::string tempStr = DPL::ToUTF8String(m_updatePeriod); + + //set standard locale to fix decimal point mark - '.' + std::string currentLocale = setlocale(LC_NUMERIC, NULL); + if (NULL == setlocale(LC_NUMERIC, "C")) + _W("Failed to change locale to \"C\""); + double updatePeriod = strtod(tempStr.c_str(), &endptr); + + //go back to previous locale + if (NULL == setlocale(LC_NUMERIC, currentLocale.c_str())) + _W("Failed to set previous locale"); + + if ((errno == ERANGE && (updatePeriod == -HUGE_VAL || updatePeriod == HUGE_VAL)) + || *endptr != '\0') { + ThrowMsg(Exception::ParseError, + "update-period attribute of app-widget element should be a number - ignoring. current value: " << m_updatePeriod); + } else if (updatePeriod < 1800.0) { + _D("update-period attribute of app-widget element shouldn't be less than 1800.0 - changed to 1800 from value: %ls", m_updatePeriod.c_str()); + m_updatePeriod = L"1800.0"; + } + } + + if (m_autoLaunch.empty() || CheckIfNotTrueNorFalse(m_autoLaunch)) + { + m_autoLaunch = L"false"; // default value + } + + if(m_livebox.m_label.empty()) { + ThrowMsg(Exception::ParseError, + "box-label element of app-widget element not found - ignoring"); + } + + if(!m_boxContentFound) { + ThrowMsg(Exception::ParseError, + "box-content element of app-widget element not found - ignoring"); + } + + m_livebox.m_liveboxId = m_liveboxId; + m_livebox.m_primary = m_primary; + m_livebox.m_autoLaunch = m_autoLaunch; + m_livebox.m_updatePeriod = m_updatePeriod; + m_livebox.m_type = m_type; + + m_data.m_livebox.push_back(m_livebox); + } + + explicit AppWidgetParser(ConfigParserData& data) : + ElementParser(), + m_data(data), + m_properNamespace(false), + m_boxContentFound(false) + { + m_livebox = ConfigParserData::LiveboxInfo(); + } + + ElementParserPtr OnBoxLabelElement() + { + + return ElementParserPtr(new BoxLabelParser(m_livebox)); + } + + ElementParserPtr OnBoxIconElement() + { + return ElementParserPtr(new BoxIconParser(m_livebox)); + } + + ElementParserPtr OnBoxContentElement() + { + m_boxContentFound = true; + return ElementParserPtr(new BoxContentParser(m_livebox)); + } + + private: + static std::string REGEXP_ID_STRING; + ConfigParserData& m_data; + ConfigParserData::LiveboxInfo m_livebox; + DPL::String m_liveboxId; + DPL::String m_primary; + DPL::String m_autoLaunch; + DPL::String m_updatePeriod; + DPL::String m_type; + bool m_properNamespace; + bool m_boxContentFound; + + static bool CheckIfNotTrueNorFalse(const DPL::String &stringToCheck) + { + return stringToCheck.compare(L"true") != 0 && stringToCheck.compare(L"false") != 0; + } +}; + +std::string AppWidgetParser::REGEXP_ID_STRING = std::string(ApplicationParser::REGEXP_ID) + "\\.[0-9A-Za-z]+"; +#endif + +class AllowNavigationParser : public ElementParser +{ + public: + AllowNavigationParser(ConfigParserData& data) : + ElementParser(), + m_data(data), + m_properNamespace(false) + {} + + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& /*name*/) + { + return &IgnoringParser::Create; //ignore unknown according to w3c + } + + virtual void Accept(const Element& element) + { + if (element.ns == ConfigurationNamespace::TizenWebAppNamespaceName) { + m_properNamespace = true; + } + } + + virtual void Accept(const Text& text) + { + if (m_properNamespace) + { + m_origin = text.value; + } + } + + virtual void Accept(const XmlAttribute& /*attribute*/) + { + } + + virtual void Verify() + { + if (m_data.allowNavigationEncountered || !m_properNamespace) + { + return; + } + m_data.allowNavigationEncountered = true; + + if (!m_origin) { + _W("data is empty"); + return; + } + + char* data = strdup(DPL::ToUTF8String(*m_origin).c_str()); + char* ptr = strtok(data," \n\r\t"); + while (ptr != NULL) { + std::string origin = ptr; + ptr = strtok(NULL," \n\r\t"); + if(origin == "*") { + ConfigParserData::AllowNavigationInfo info(L"*", L"*"); + m_data.allowNavigationInfoList.push_back(info); + continue; + } + + std::unique_ptr iri(iri_parse(origin.c_str()), iri_destroy); + if (!iri->host || strlen(iri->host) == 0) { + // input origin should has schem and host + // in case of file scheme path is filled + // "http://" + _W("input origin isn't verified"); + continue; + } + DPL::String scheme = L"*"; + if (iri->scheme && strlen(iri->scheme) != 0) { + scheme = DPL::FromUTF8String(iri->scheme); + } + ConfigParserData::AllowNavigationInfo info( + scheme, + DPL::FromUTF8String(iri->host)); + m_data.allowNavigationInfoList.push_back(info); + } + free(data); + } + + private: + DPL::OptionalString m_origin; + ConfigParserData& m_data; + bool m_properNamespace; +}; + +class CspParser : public ElementParser +{ + public: + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& /*name*/) + { + return &IgnoringParser::Create; //ignore unknown according to w3c + } + + CspParser(ConfigParserData& data) : + ElementParser(), + m_data(data), + m_properNamespace(false) + {} + + virtual void Accept(const Element& element) + { + if (element.ns == ConfigurationNamespace::TizenWebAppNamespaceName) { + m_properNamespace = true; + } + } + + virtual void Accept(const XmlAttribute& /*attribute*/) + {} + + virtual void Accept(const Text& text) + { + if (m_properNamespace) { + m_policy = text.value; + } + } + + virtual void Verify() + { + if (m_data.cspPolicyEncountered) { + return; + } + m_data.cspPolicyEncountered = true; + + if (!!m_policy) { + m_data.cspPolicy = *m_policy; + } + } + + private: + ConfigParserData& m_data; + bool m_properNamespace; + DPL::OptionalString m_policy; +}; + +class CspReportOnlyParser : public ElementParser +{ + public: + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& /*name*/) + { + return &IgnoringParser::Create; //ignore unknown according to w3c + } + + CspReportOnlyParser(ConfigParserData& data) : + ElementParser(), + m_data(data), + m_properNamespace(false) + {} + + virtual void Accept(const Element& element) + { + if (element.ns == ConfigurationNamespace::TizenWebAppNamespaceName) { + m_properNamespace = true; + } + } + + virtual void Accept(const XmlAttribute& /*attribute*/) + {} + + virtual void Accept(const Text& text) + { + if (m_properNamespace) { + m_policy = text.value; + } + } + + virtual void Verify() + { + if (m_data.cspPolicyReportOnlyEncountered) { + return; + } + m_data.cspPolicyReportOnlyEncountered = true; + + if (!!m_policy) { + m_data.cspPolicyReportOnly = *m_policy; + } + } + + private: + ConfigParserData& m_data; + bool m_properNamespace; + DPL::OptionalString m_policy; +}; + +class AccountParser : public ElementParser +{ + public: + struct IconParser : public ElementParser + { + public: + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& /*name*/) + { + return &IgnoringParser::Create; //ignore unknown according to w3c + } + + virtual void Accept(const Text& text) + { + if (text.value == L"") { + return; + } + m_value = text.value; + } + + virtual void Accept(const Element& /*element*/) + {} + + virtual void Accept(const XmlAttribute& attribute) + { + if (attribute.name == L"section") { + if (attribute.value == L"Account") { + m_type = ConfigParserData::IconSectionType::DefaultIcon; + } else if (attribute.value == L"AccountSmall") { + m_type = ConfigParserData::IconSectionType::SmallIcon; + } + } + } + + virtual void Verify() + { + if (!m_value || *m_value == L"") { + return; + } + + std::pair icon; + icon.first = m_type; + icon.second = *m_value; + + m_data.m_iconSet.insert(icon); + } + + IconParser(ConfigParserData::AccountProvider& data) : + ElementParser(), + m_properNamespace(false), + m_type(ConfigParserData::DefaultIcon), + m_data(data) + {} + + private: + bool m_properNamespace; + ConfigParserData::IconSectionType m_type; + ConfigParserData::AccountProvider& m_data; + DPL::OptionalString m_value; + }; + + struct DisplayNameParser : public ElementParser + { + public: + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& /*name*/) + { + return &IgnoringParser::Create; //ignore unknown according to w3c + } + + virtual void Accept(const Text& text) + { + if (text.value == L"") { + return; + } + m_value = text.value; + } + + virtual void Accept(const Element& element) + { + m_lang = element.lang; + m_value= L""; + } + + virtual void Accept(const XmlAttribute& /*attribute*/) + {} + + virtual void Verify() + { + if (!m_value || *m_value == L"") { + return; + } + + std::pair name; + name.first = *m_lang; + name.second = *m_value; + + m_data.m_displayNameSet.insert(name); + } + + DisplayNameParser(ConfigParserData::AccountProvider& data) : + ElementParser(), + m_properNamespace(false), + m_data(data) + {} + + private: + bool m_properNamespace; + DPL::OptionalString m_lang; + DPL::OptionalString m_value; + ConfigParserData::AccountProvider& m_data; + }; + + struct CapabilityParser : public ElementParser + { + public: + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& /*name*/) + { + return &IgnoringParser::Create; //ignore unknown according to w3c + } + + virtual void Accept(const Text& text) + { + if (text.value == L"") { + return; + } + m_value = text.value; + } + + virtual void Accept(const Element& /*element*/) + {} + + virtual void Accept(const XmlAttribute& /*attribute*/) + {} + + virtual void Verify() + { + if (!m_value || *m_value == L"") { + return; + } + m_data.m_capabilityList.push_back(*m_value); + } + + CapabilityParser(ConfigParserData::AccountProvider& data) : + ElementParser(), + m_properNamespace(false), + m_data(data) + {} + + private: + bool m_properNamespace; + DPL::OptionalString m_value; + ConfigParserData::AccountProvider& m_data; + }; + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& name) + { + if (name == L"icon") { + return std::bind(&AccountParser::OnIconElement, this); + } else if (name == L"display-name") { + return std::bind(&AccountParser::OnDisplayNameElement, this); + } else if (name == L"capability") { + return std::bind(&AccountParser::OnCapabilityElement, this); + } else { + return &IgnoringParser::Create; //ignore unknown according to w3c + } + } + + virtual void Accept(const Text& /*text*/) + {} + + virtual void Accept(const Element& /*element*/) + {} + + virtual void Accept(const XmlAttribute& attribute) + { + if (attribute.name == L"multiple-account-support") { + if (attribute.value == L"true") { + m_account.m_multiAccountSupport = true; + } + } + } + + virtual void Verify() + { + } + + ElementParserPtr OnIconElement() + { + return ElementParserPtr(new IconParser(m_account)); + } + + ElementParserPtr OnDisplayNameElement() + { + return ElementParserPtr(new DisplayNameParser(m_account)); + } + + ElementParserPtr OnCapabilityElement() + { + return ElementParserPtr(new CapabilityParser(m_account)); + } + + AccountParser(ConfigParserData& data) : + ElementParser(), + m_properNamespace(false), + m_multiSupport(false), + m_data(data), + m_account(data.accountProvider) + { + } + + private: + bool m_properNamespace; + bool m_multiSupport; + ConfigParserData& m_data; + ConfigParserData::AccountProvider& m_account; +}; + +class MetadataParser : public ElementParser +{ + public: + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& /*name*/) + { + return &IgnoringParser::Create; //ignore unknown according to w3c + } + + virtual void Accept(const XmlAttribute& attribute) + { + if (m_properNamespace) { + if (attribute.name == L"key") { + m_key = attribute.value; + } else if (attribute.name == L"value") { + m_value = attribute.value; + } + } + } + + virtual void Accept(const Element& element) + { + if (element.ns == ConfigurationNamespace::TizenWebAppNamespaceName) { + m_properNamespace = true; + } + } + + virtual void Accept(const Text& /*text*/) + { + ThrowMsg(Exception::ParseError, "param element must be empty"); + } + + virtual void Verify() + { + if (!m_key) { + _W("metadata element must have key attribute"); + return; + } + NormalizeString(m_key); + NormalizeString(m_value); + ConfigParserData::Metadata metaData(m_key, m_value); + FOREACH(it, m_data.metadataList) { + if (!DPL::StringCompare(*it->key, *m_key)) { + _E("Key isn't unique"); + return; + } + } + m_data.metadataList.push_back(metaData); + } + + MetadataParser(ConfigParserData& data) : + ElementParser(), + m_data(data), + m_properNamespace(false) + {} + + private: + DPL::OptionalString m_key; + DPL::OptionalString m_value; + ConfigParserData& m_data; + bool m_properNamespace; +}; + +#ifdef IME_ENABLED +class ImeParser : public ElementParser +{ + public: + struct UuidParser : public ElementParser + { + public: + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& /*name*/) + { + return &IgnoringParser::Create; + } + + virtual void Accept(const XmlAttribute& attribute) + {} + + virtual void Accept(const Element& element) + {} + + virtual void Accept(const Text& text) + { + if (m_uuid.empty()) { + m_uuid = text.value; + } else { + m_uuid += text.value; + } + } + + virtual void Verify() + { + if (m_uuid.empty()) { + ThrowMsg(Exception::ParseError, "uuid text is empty"); + } + m_imeAppInfo.uuid = m_uuid; + } + + UuidParser(ConfigParserData::ImeAppInfo& data) : + ElementParser(), + m_imeAppInfo(data) + {} + + private: + ConfigParserData::ImeAppInfo& m_imeAppInfo; + DPL::String m_uuid; + }; + + struct LanguagesParser : public ElementParser + { + public: + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& name) + { + if (name == L"language") { + return std::bind(&LanguagesParser::OnLanguageElement, this); + } else { + return &IgnoringParser::Create; + } + } + + virtual void Accept(const XmlAttribute& attribute) + {} + + virtual void Accept(const Element& element) + {} + + virtual void Accept(const Text& text) + { + ThrowMsg(Exception::ParseError, "param element must be empty"); + } + + virtual void Verify() + {} + + LanguagesParser(ConfigParserData::ImeAppInfo& data) : + ElementParser(), + m_imeAppInfo(data) + {} + + ElementParserPtr OnLanguageElement() + { + return ElementParserPtr(new LanguageParser(m_imeAppInfo)); + } + + private: + ConfigParserData::ImeAppInfo& m_imeAppInfo; + }; + + struct LanguageParser : public ElementParser + { + public: + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& name) + { + return &IgnoringParser::Create; + } + + virtual void Accept(const XmlAttribute& attribute) + {} + + virtual void Accept(const Element& element) + {} + + virtual void Accept(const Text& text) + { + if (m_language.empty()) { + m_language = text.value; + } else { + m_language += text.value; + } + } + + virtual void Verify() + { + if (m_language.empty()) { + ThrowMsg(Exception::ParseError, "language text is empty"); + } + m_imeAppInfo.languageList.insert(m_language); + } + + LanguageParser(ConfigParserData::ImeAppInfo& data) : + ElementParser(), + m_imeAppInfo(data) + {} + + private: + ConfigParserData::ImeAppInfo& m_imeAppInfo; + DPL::String m_language; + }; + + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& name) + { + if (name == L"uuid") { + return std::bind(&ImeParser::OnUuidElement, this); + } else if (name == L"languages") { + return std::bind(&ImeParser::OnLanguagesElement, this); + } else { + return &IgnoringParser::Create; + } + } + + virtual void Accept(const Text& /*text*/) + { + ThrowMsg(Exception::ParseError, "param element must be empty"); + } + + virtual void Accept(const Element& element) + {} + + virtual void Accept(const XmlAttribute& attribute) + {} + + virtual void Verify() + { + if (m_imeAppInfo.uuid.empty()) { + ThrowMsg(Exception::ParseError, "ime element must have uuid element"); + return; + } + + if (m_imeAppInfo.languageList.empty()) { + ThrowMsg(Exception::ParseError, "ime element must have language element"); + return; + } + m_data.imeAppInfoList.push_back(m_imeAppInfo); + } + + ImeParser(ConfigParserData& data) : + ElementParser(), + m_data(data), + m_imeAppInfo() + {} + + ElementParserPtr OnLanguagesElement() + { + return ElementParserPtr(new LanguagesParser(m_imeAppInfo)); + } + + ElementParserPtr OnUuidElement() + { + return ElementParserPtr(new UuidParser(m_imeAppInfo)); + } + + private: + ConfigParserData& m_data; + ConfigParserData::ImeAppInfo m_imeAppInfo; +}; +#endif + +#ifdef SERVICE_ENABLED +class ServiceAppParser : public ElementParser +{ + public: + struct ServiceContentParser : public ElementParser + { + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& /*name*/) + { + return &IgnoringParser::Create; //ignore unknown according to w3c + } + + virtual void Accept(const XmlAttribute& attribute) + { + if (attribute.name == L"src") { + m_src = attribute.value; + } + } + + virtual void Accept(const Element& element) + {} + + virtual void Accept(const Text& /*text*/) + { + ThrowMsg(Exception::ParseError, "param element must be empty"); + } + + virtual void Verify() + { + if (m_src.empty()) { + ThrowMsg(Exception::ParseError, "src attribute of service-content element is mandatory"); + } + + if (!m_serviceAppInfo.serviceContent.empty()) { + ThrowMsg(Exception::ParseError, "service-content element occurs more than 1 time"); + } + m_serviceAppInfo.serviceContent = m_src; + } + + explicit ServiceContentParser(ConfigParserData::ServiceAppInfo& data) : + ElementParser(), + m_serviceAppInfo(data) + {} + + private: + DPL::String m_src; + ConfigParserData::ServiceAppInfo& m_serviceAppInfo;; + }; + + struct ServiceNameParser : public ElementParser + { + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& /*name*/) + { + return &IgnoringParser::Create; + } + + virtual void Accept(const XmlAttribute& attribute) + { + m_lang = attribute.lang; + } + + virtual void Accept(const Element& element) + {} + + virtual void Accept(const Text& text) + { + m_name = text.value; + } + + virtual void Verify() + { + ConfigParserData::LocalizedData& data = m_serviceAppInfo.m_localizedDataSet[m_lang]; + if (data.name.IsNull()) { + NormalizeString(m_name); + data.name = m_name; + } + } + + ServiceNameParser(ConfigParserData::ServiceAppInfo& data) : + ElementParser(), + m_serviceAppInfo(data) + {} + + private: + DPL::String m_lang; + DPL::String m_name; + ConfigParserData::ServiceAppInfo& m_serviceAppInfo; + }; + + struct ServiceIconParser : public ElementParser + { + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& /*name*/) + { + return &IgnoringParser::Create; + } + + virtual void Accept(const XmlAttribute& attribute) + { + if (attribute.name == L"src") { + m_icon.src = attribute.value; + } + else if (attribute.name == L"width") { + m_icon.width = ConvertToInt(attribute.value); + } + else if (attribute.name == L"height") { + m_icon.height = ConvertToInt(attribute.value); + } + } + + virtual void Accept(const Element& element) + {} + + virtual void Accept(const Text& /*text*/) + { + ThrowMsg(Exception::ParseError, "param element must be empty"); + } + + virtual void Verify() + { + if (m_icon.src.empty()) { + ThrowMsg(Exception::ParseError, + "src attribute of service-icon element is mandatory - ignoring"); + } + m_serviceAppInfo.m_iconsList.push_back(m_icon); + } + + explicit ServiceIconParser(ConfigParserData::ServiceAppInfo& data) : + ElementParser(), + m_icon(L""), + m_serviceAppInfo(data) + {} + + private: + DPL::OptionalInt ConvertToInt(const DPL::String& intAsString) + { + char * endptr; + std::string tempStr = DPL::ToUTF8String(intAsString); + const char * intAsString_c = tempStr.c_str(); + errno = 0; + long int intAsString_i = strtol(intAsString_c, &endptr, 10); + + if ((errno == ERANGE && (intAsString_i == LONG_MAX || intAsString_i == LONG_MIN)) + || intAsString_i > INT_MAX || intAsString_i < INT_MIN + || *endptr != '\0') { + return DPL::OptionalInt(); + } + + return static_cast(intAsString_i); + } + + private: + ConfigParserData::Icon m_icon; + ConfigParserData::ServiceAppInfo& m_serviceAppInfo; + }; + + struct ServiceDescriptionParser : public ElementParser + { + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, const DPL::String& /*name*/) + { + return &IgnoringParser::Create; //ignore unknown according to w3c + } + + virtual void Accept(const XmlAttribute& attribute) + { + m_lang = attribute.lang; + } + virtual void Accept(const Element& element) + {} + + virtual void Accept(const Text& text) + { + m_description = text.value; + } + + virtual void Verify() + { + ConfigParserData::LocalizedData& data = m_serviceAppInfo.m_localizedDataSet[m_lang]; + if (data.description.IsNull()) { + NormalizeString(m_description); + data.description = m_description; + } + } + + ServiceDescriptionParser(ConfigParserData::ServiceAppInfo& data) : + ElementParser(), + m_serviceAppInfo(data) + {} + + private: + DPL::String m_lang; + DPL::String m_description; + ConfigParserData::ServiceAppInfo& m_serviceAppInfo; + }; + + virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, + const DPL::String& name) + { + if (name == L"service-content") { + return std::bind(&ServiceAppParser::OnServiceContentElement, this); + } else if (name == L"service-name") { + return std::bind(&ServiceAppParser::OnServiceNameElement, this); + } else if (name == L"service-icon") { + return std::bind(&ServiceAppParser::OnServiceIconElement, this); + } else if (name == L"service-description") { + return std::bind(&ServiceAppParser::OnServiceDescriptionElement, this); + } else { + return &IgnoringParser::Create; + } + } + + virtual void Accept(const Element& element) + {} + + virtual void Accept(const XmlAttribute& attribute) + { + if (attribute.name == L"id") { + if (attribute.value.size() > 0) { + m_serviceId = attribute.value; + } + } else if (attribute.name == L"auto_restart") { + if (attribute.value == L"true") { + m_autoRestart = true; + } else if (attribute.value == L"false") { + m_autoRestart = false; + } else { + ThrowMsg(Exception::ParseError, "Wrong boolean value"); + } + } else if (attribute.name == L"on_boot") { + if (attribute.value == L"true") { + m_onBoot = true; + } else if (attribute.value == L"false") { + m_onBoot = false; + } else { + ThrowMsg(Exception::ParseError, "Wrong boolean value"); + } + } + } + + virtual void Accept(const Text& /*text*/) + { + ThrowMsg(Exception::ParseError, "param element must be empty"); + } + + virtual void Verify() + { + if (m_serviceAppInfo.serviceContent.empty()) { + ThrowMsg(Exception::ParseError, "service element must have service-content element"); + return; + } + + if (m_serviceId.empty()) { + ThrowMsg(Exception::ParseError, "service attribute must have id attribute"); + return; + } + m_serviceAppInfo.serviceId = m_serviceId; + + m_serviceAppInfo.autoRestart = m_autoRestart; + + m_serviceAppInfo.onBoot = m_onBoot; + + m_data.serviceAppInfoList.push_back(m_serviceAppInfo); + } + + ServiceAppParser(ConfigParserData& data) : + ElementParser(), + m_data(data), + m_serviceAppInfo(), + m_onBoot(false), + m_autoRestart(false) + {} + + ElementParserPtr OnServiceContentElement() + { + return ElementParserPtr(new ServiceContentParser(m_serviceAppInfo)); + } + + ElementParserPtr OnServiceNameElement() + { + return ElementParserPtr(new ServiceNameParser(m_serviceAppInfo)); + } + + ElementParserPtr OnServiceIconElement() + { + return ElementParserPtr(new ServiceIconParser(m_serviceAppInfo)); + } + + ElementParserPtr OnServiceDescriptionElement() + { + return ElementParserPtr(new ServiceDescriptionParser(m_serviceAppInfo)); + } + + private: + DPL::String m_serviceId; + ConfigParserData& m_data; + ConfigParserData::ServiceAppInfo m_serviceAppInfo; + bool m_autoRestart; + bool m_onBoot; +}; +#endif + +ElementParser::ActionFunc WidgetParser::GetElementParser( + const DPL::String& /*ns*/, + const DPL::String& name) +{ + FuncMap::const_iterator it = m_map.find(name); + if (it != m_map.end()) { + return it->second; + } else { + return &IgnoringParser::Create; //ignore unknown according to w3c + } +} + +WidgetParser::WidgetParser(ConfigParserData& data) : + m_data(data), + m_textDirection(Unicode::EMPTY) +{ + m_map[L"name"] = std::bind(&WidgetParser::OnNameElement, this); + m_map[L"access"] = std::bind(&WidgetParser::OnAccessElement, this); + m_map[L"description"] = std::bind(&WidgetParser::OnDescriptionElement, this); + m_map[L"author"] = std::bind(&WidgetParser::OnAuthorElement, this); + m_map[L"license"] = std::bind(&WidgetParser::OnLicenseElement, this); + m_map[L"icon"] = std::bind(&WidgetParser::OnIconElement, this); + m_map[L"small-icon"] = std::bind(&WidgetParser::OnSmallIconElement, this); + m_map[L"content"] = std::bind(&WidgetParser::OnContentElement, this); + m_map[L"preference"] = std::bind(&WidgetParser::OnPreferenceElement, this); + m_map[L"setting"] = std::bind(&WidgetParser::OnSettingElement, this); + m_map[L"application"] = std::bind(&WidgetParser::OnApplicationElement, this); +#ifdef IME_ENABLED + m_map[L"ime"] = std::bind(&WidgetParser::OnImeElement, this); +#endif +#ifdef SERVICE_ENABLED + m_map[L"service"] = std::bind(&WidgetParser::OnServiceAppElement, this); +#endif + m_map[L"splash"] = std::bind(&WidgetParser::OnSplashElement, this); + m_map[L"background"] = std::bind(&WidgetParser::OnBackgroundElement, this); + m_map[L"privilege"] = std::bind(&WidgetParser::OnPrivilegeElement, this); + m_map[L"app-control"] = std::bind(&WidgetParser::OnAppControlElement, this); + m_map[L"category"] = std::bind(&WidgetParser::OnCategoryElement, this); +#ifdef DBOX_ENABLED + m_map[L"app-widget"] = std::bind(&WidgetParser::OnAppWidgetElement, this); +#endif +#if ENABLE(CONTENT_SECURITY_POLICY) + m_map[L"content-security-policy"] = std::bind(&WidgetParser::OnCspElement, this); + m_map[L"content-security-policy-report-only"] = std::bind(&WidgetParser::OnCspReportOnlyElement, this); +#endif +#if ENABLE(ALLOW_NAVIGATION) + m_map[L"allow-navigation"] = std::bind(&WidgetParser::OnAllowNavigationElement, this); +#endif + m_map[L"account"] = std::bind(&WidgetParser::OnAccountElement, this); + m_map[L"metadata"] = std::bind(&WidgetParser::OnMetadataElement, this); +} + +ElementParserPtr WidgetParser::OnNameElement() +{ + return ElementParserPtr(new NameParser(m_textDirection, m_data)); +} + +ElementParserPtr WidgetParser::OnAccessElement() +{ + return ElementParserPtr(new AccessParser(m_data)); +} + +ElementParserPtr WidgetParser::OnDescriptionElement() +{ + return ElementParserPtr(new DescriptionParser(m_textDirection, m_data)); +} + +ElementParserPtr WidgetParser::OnAuthorElement() +{ + return ElementParserPtr(new AuthorParser(m_textDirection, m_data)); +} + +ElementParserPtr WidgetParser::OnLicenseElement() +{ + return ElementParserPtr(new LicenseParser(m_textDirection, m_data)); +} + +ElementParserPtr WidgetParser::OnIconElement() +{ + return ElementParserPtr(new IconParser(m_data)); +} + +ElementParserPtr WidgetParser::OnSmallIconElement() +{ + return ElementParserPtr(new IconParser(m_data, true)); +} + +ElementParserPtr WidgetParser::OnContentElement() +{ + return ElementParserPtr(new ContentParser(m_data)); +} + +ElementParserPtr WidgetParser::OnPreferenceElement() +{ + return ElementParserPtr(new PreferenceParser(m_data)); +} + +ElementParserPtr WidgetParser::OnSettingElement() +{ + return ElementParserPtr(new SettingParser(m_data)); +} + +ElementParserPtr WidgetParser::OnApplicationElement() +{ + return ElementParserPtr(new ApplicationParser(m_data)); +} + +ElementParserPtr WidgetParser::OnSplashElement() +{ + return ElementParserPtr(new SplashParser(m_data)); +} + +ElementParserPtr WidgetParser::OnBackgroundElement() +{ + return ElementParserPtr(new BackgroundParser(m_data)); +} + +ElementParserPtr WidgetParser::OnPrivilegeElement() +{ + return ElementParserPtr(new PrivilegeParser(m_data)); +} + +ElementParserPtr WidgetParser::OnAppControlElement() +{ + return ElementParserPtr(new AppControlParser(m_data)); +} + +ElementParserPtr WidgetParser::OnCategoryElement() +{ + return ElementParserPtr(new CategoryParser(m_data)); +} + +#ifdef DBOX_ENABLED +ElementParserPtr WidgetParser::OnAppWidgetElement() +{ + return ElementParserPtr(new AppWidgetParser(m_data)); +} +#endif + +ElementParserPtr WidgetParser::OnCspElement() +{ + return ElementParserPtr(new CspParser(m_data)); +} + +ElementParserPtr WidgetParser::OnCspReportOnlyElement() +{ + return ElementParserPtr(new CspReportOnlyParser(m_data)); +} + +ElementParserPtr WidgetParser::OnAllowNavigationElement() +{ + return ElementParserPtr(new AllowNavigationParser(m_data)); +} + +ElementParserPtr WidgetParser::OnAccountElement() +{ + return ElementParserPtr(new AccountParser(m_data)); +} + +ElementParserPtr WidgetParser::OnMetadataElement() +{ + return ElementParserPtr(new MetadataParser(m_data)); +} + +#ifdef IME_ENABLED +ElementParserPtr WidgetParser::OnImeElement() +{ + return ElementParserPtr(new ImeParser(m_data)); +} +#endif + +#ifdef SERVICE_ENABLED +ElementParserPtr WidgetParser::OnServiceAppElement() +{ + return ElementParserPtr(new ServiceAppParser(m_data)); +} +#endif + +void WidgetParser::Accept(const Element& element) +{ + if (element.ns != ConfigurationNamespace::W3CWidgetNamespaceName && + element.ns != ConfigurationNamespace::TizenWebAppNamespaceName) + { + ThrowMsg(Exception::ParseError, + "Wrong xml namespace for widget element"); + } +} + +void WidgetParser::Accept(const Text& /*text*/) +{ + ThrowMsg(Exception::ParseError, "widged element must be empty"); +} + +void WidgetParser::Accept(const XmlAttribute& attribute) +{ + if (attribute.name == L"id") { + LibIri::Wrapper iri(DPL::ToUTF8String(attribute.value).c_str()); + //If may important tests starts to fail this test we will have + //to consider commenting this test out again. + if (iri.Validate()) { + m_data.widget_id = attribute.value; + NormalizeString(m_data.widget_id); + } else { + _W("Widget id validation failed: %ls", attribute.value.c_str()); + } + } else if (attribute.name == L"version") { + m_version = attribute.value; + NormalizeString(m_version); + } else if (attribute.name == L"min-version") { + _D("min-version attribute was found. Value: %ls", attribute.value.c_str()); + m_minVersion = attribute.value; + NormalizeString(m_minVersion); + m_data.minVersionRequired = m_minVersion; + } else if (attribute.name == L"height") { + DPL::OptionalString value = attribute.value; + NormalizeString(value); + std::string v = DPL::ToUTF8String(*value); + + if (!v.empty()) { + unsigned char c = v.c_str()[0]; + if (isdigit(c)) { + int val = 0; + for (size_t i = 0; i < v.size(); ++i) { + c = v.c_str()[i]; + if (isdigit(c)) { + val *= 10; + val += (c - '0'); + } else { + break; + } + } + m_data.height = val; + } + } + } else if (attribute.name == L"width") { + DPL::OptionalString value = attribute.value; + NormalizeString(value); + std::string v = DPL::ToUTF8String(*value); + + if (!v.empty()) { + unsigned char c = v.c_str()[0]; + if (c >= '0' && c <= '9') { + int val = 0; + for (size_t i = 0; i < v.size(); ++i) { + c = v.c_str()[i]; + if (c >= '0' && c <= '9') { + val *= 10; + val += (c - '0'); + } else { + break; + } + } + m_data.width = val; + } + } + } else if (attribute.name == L"viewmodes") { + DPL::Tokenize(attribute.value, + L" ", + std::inserter(m_windowModes, + m_windowModes.end()), + true); + } else if (attribute.name == L"dir") { + m_textDirection = Unicode::ParseDirAttribute(attribute); + } else if (L"defaultlocale" == attribute.name) { + if (!m_defaultlocale) { + m_defaultlocale = attribute.value; + NormalizeString(m_defaultlocale); + std::string dl = DPL::ToUTF8String(*m_defaultlocale); + + if (!LanguageSubtagRstTreeSingleton::Instance(). + ValidateLanguageTag(dl)) { + _W("Language tag: %s is not valid", dl.c_str()); + m_defaultlocale = DPL::OptionalString(); + } else { + _D("Default locale found %s", dl.c_str()); + } + } else { + _W("Ignoring subsequent default locale"); + } + //Any other value consider as a namespace definition + } else if (attribute.name == L"xmlns" || attribute.prefix == L"xmlns") { + _D("Namespace domain: %ls", attribute.name.c_str()); + _D("Namespace value: %ls", attribute.value.c_str()); + m_nameSpaces[attribute.name] = attribute.value; + } + else { + _E("Unknown attirbute: namespace=%ls, name=%ls, value=%ls", + attribute.ns.c_str(), attribute.name.c_str(), attribute.value.c_str()); + } +} + +void WidgetParser::Verify() +{ + FOREACH(mode, m_windowModes) { + if (L"windowed" == *mode || L"floating" == *mode || + L"fullscreen" == *mode || L"maximized" == *mode || + L"minimized" == *mode) + { + m_data.windowModes.insert(*mode); + } + } + if (!!m_version) { + Unicode::UpdateTextWithDirectionMark(m_textDirection, &*m_version); + m_data.version = m_version; + } + m_data.defaultlocale = m_defaultlocale; + FOREACH(ns, m_nameSpaces) { + m_data.nameSpaces.insert(ns->second); + } +} diff --git a/src_wearable/configuration_parser/widget_parser.h b/src_wearable/configuration_parser/widget_parser.h new file mode 100755 index 0000000..13cef2f --- /dev/null +++ b/src_wearable/configuration_parser/widget_parser.h @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * This file have been implemented in compliance with W3C WARP SPEC. + * but there are some patent issue between W3C WARP SPEC and APPLE. + * so if you want to use this file, refer to the README file in root directory + */ +/** + * @file widget_parser.h + * @author Lukasz Wrzosek (l.wrzosek@samsung.com) + * @version 0.1 + * @brief + */ +#ifndef WIDGET_PARSER_H_ +#define WIDGET_PARSER_H_ + +#include "element_parser.h" +#include +#include +#include +#include +#include + +namespace ConfigurationNamespace { +static const DPL::String W3CWidgetNamespaceName = + L"http://www.w3.org/ns/widgets"; +static const DPL::String TizenWebAppNamespaceName = + L"http://tizen.org/ns/widgets"; +} + +namespace PluginsPrefix { +const char * const W3CPluginsPrefix = "http://www.w3.org/"; +const char * const TIZENPluginsPrefix = "http://tizen.org/api/"; +} + +namespace Unicode { +enum Direction +{ + LRE, + RLE, + LRO, + RLO, + EMPTY +}; +} + +class WidgetParser : public ElementParser +{ + public: + ElementParserPtr OnNameElement(); + ElementParserPtr OnDescriptionElement(); + ElementParserPtr OnAuthorElement(); + ElementParserPtr OnLicenseElement(); + ElementParserPtr OnIconElement(); + ElementParserPtr OnSmallIconElement(); + ElementParserPtr OnContentElement(); + ElementParserPtr OnPreferenceElement(); + ElementParserPtr OnAccessElement(); + ElementParserPtr OnSettingElement(); + ElementParserPtr OnApplicationElement(); + ElementParserPtr OnSplashElement(); + ElementParserPtr OnBackgroundElement(); + ElementParserPtr OnPrivilegeElement(); + ElementParserPtr OnAppControlElement(); + ElementParserPtr OnCategoryElement(); + ElementParserPtr OnAppWidgetElement(); + ElementParserPtr OnCspElement(); + ElementParserPtr OnCspReportOnlyElement(); + ElementParserPtr OnAllowNavigationElement(); + ElementParserPtr OnAccountElement(); + ElementParserPtr OnMetadataElement(); + +#ifdef IME_ENABLED + ElementParserPtr OnImeElement(); +#endif +#ifdef SERVICE_ENABLED + ElementParserPtr OnServiceAppElement(); +#endif + + virtual ActionFunc GetElementParser(const DPL::String& ns, + const DPL::String& name); + + virtual void Accept(const Element&); + virtual void Accept(const Text&); + virtual void Accept(const XmlAttribute&); + virtual void Verify(); + + //Typedef used by RootParser + typedef WrtDB::ConfigParserData& Data; + + WidgetParser(Data&); + + private: + Data& m_data; + Unicode::Direction m_textDirection; + FuncMap m_map; + DPL::OptionalString m_version; + DPL::OptionalString m_minVersion; + std::list m_windowModes; + DPL::OptionalString m_defaultlocale; + std::map m_nameSpaces; +}; + +struct IconParser; +struct ContentParser; + +#endif // WIDGET_PARSER_H_ diff --git a/src_wearable/jobs/job.cpp b/src_wearable/jobs/job.cpp new file mode 100644 index 0000000..ec2bb7f --- /dev/null +++ b/src_wearable/jobs/job.cpp @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include + +namespace Jobs { +Job::Job(InstallationType installType) : + m_handle(0), + m_installationType(installType), + m_abortStarted(false), + m_paused(false) +{} + +InstallationType Job::GetInstallationType() const +{ + return m_installationType; +} + +bool Job::GetAbortStarted() const +{ + return m_abortStarted; +} + +void Job::SetAbortStarted(bool flag) +{ + m_abortStarted = flag; +} + +bool Job::IsPaused() const +{ + return m_paused; +} + +void Job::SetPaused(bool paused) +{ + if (paused) { + Pause(); + } else { + Resume(); + } +} + +void Job::Pause() +{ + if (m_paused) { + return; + } + + // Pause + m_paused = true; +} + +void Job::Resume() +{ + if (!m_paused) { + return; + } + + // Continue + m_paused = false; + + // Trigger next steps + CONTROLLER_POST_EVENT(Logic::InstallerController, + InstallerControllerEvents::NextStepEvent(this)); +} + +void Job::SetJobHandle(JobHandle handle) +{ + m_handle = handle; +} + +JobHandle Job::GetJobHandle() const +{ + return m_handle; +} + +void Job::SendProgress() +{} + +void Job::SendFinishedSuccess() +{} + +void Job::SendFinishedFailure() +{} + +void Job::SendProgressIconPath(const std::string &/*path*/) +{} + +void Job::SaveExceptionData(const Jobs::JobExceptionBase&) +{} +} //namespace Jobs diff --git a/src_wearable/jobs/job.h b/src_wearable/jobs/job.h new file mode 100644 index 0000000..3963fc6 --- /dev/null +++ b/src_wearable/jobs/job.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef INSTALLER_MODEL_H +#define INSTALLER_MODEL_H + +#include + +#include + +namespace Jobs { +class JobExceptionBase; + +typedef int JobHandle; + +class Job : + public DPL::MutableTaskList +{ + public: + Job(InstallationType installType); + + InstallationType GetInstallationType() const; + + // Undo + void SetAbortStarted(bool flag); + bool GetAbortStarted() const; + + // Pause/resume support + bool IsPaused() const; + void SetPaused(bool paused); + void Pause(); + void Resume(); + void SetJobHandle(JobHandle handle); + JobHandle GetJobHandle() const; + virtual void SendProgress(); + virtual void SendFinishedSuccess(); + virtual void SendFinishedFailure(); + virtual void SendProgressIconPath(const std::string &path); + + virtual void SaveExceptionData(const Jobs::JobExceptionBase&); + + private: + JobHandle m_handle; + InstallationType m_installationType; + bool m_abortStarted; + bool m_paused; +}; +} //namespace Jobs + +#endif // INSTALLER_MODEL_H diff --git a/src_wearable/jobs/job_base.h b/src_wearable/jobs/job_base.h new file mode 100644 index 0000000..edcf0f5 --- /dev/null +++ b/src_wearable/jobs/job_base.h @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef SRC_INSTALLER_CORE_JOBS_JOB_BASE_H +#define SRC_INSTALLER_CORE_JOBS_JOB_BASE_H + +#include + +typedef std::string ProgressDescription; +typedef float ProgressPercent; + +namespace Jobs { +template +class JobProgressBase +{ + protected: + bool m_progressFlag; + ProgressDescription m_progresDescription; + ProgressPercent m_progresPercent; + + public: + JobProgressBase() : m_progressFlag(false), + m_progresPercent(0.0) + {} + + void SetProgressFlag(bool flag) + { + m_progressFlag = flag; + } + bool GetProgressFlag() const + { + return m_progressFlag; + } + + ProgressDescription GetProgressDescription() const + { + return m_progresDescription; + } + + ProgressPercent GetProgressPercent() const + { + return m_progresPercent; + } + + void UpdateProgress(T_InstallationStep step, + ProgressDescription const &description) + { + m_progresPercent = + ((static_cast(step)) / + static_cast(lastElement)) * 100; + m_progresDescription = description; + } +}; + +template +class JobContextBase +{ + public: + JobContextBase(const T_JobStruct& jobStruct) : + m_jobStruct(jobStruct) + {} + + T_JobStruct GetInstallerStruct() const + { + return m_jobStruct; + } + + protected: + T_JobStruct m_jobStruct; +}; + +template +struct JobCallbacksBase +{ + T_finishedCb finishedCallback; + T_progressCb progressCallback; + void *userParam; + + // It must be empty-constructible as a parameter of generic event + JobCallbacksBase() : + finishedCallback(0), + progressCallback(0), + userParam(0) + {} + + JobCallbacksBase(T_finishedCb finished, + T_progressCb progress, + void *param) : + finishedCallback(finished), + progressCallback(progress), + userParam(param) + {} +}; +} //namespace Jobs + +#endif // SRC_INSTALLER_CORE_JOBS_JOB_BASE_H diff --git a/src_wearable/jobs/job_exception_base.h b/src_wearable/jobs/job_exception_base.h new file mode 100644 index 0000000..4d35420 --- /dev/null +++ b/src_wearable/jobs/job_exception_base.h @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file job_exception_base.h + * @author Pawel Sikorski (p.sikorski@samgsung.com) + * @version + * @brief + */ + +#include + +#ifndef SRC_INSTALLER_CORE_JOBS_JOB_EXCEPTION_BASE_H_ +#define SRC_INSTALLER_CORE_JOBS_JOB_EXCEPTION_BASE_H_ + +#define DECLARE_JOB_EXCEPTION_BASE(Base, Class, Param) \ + class Class : \ + public Base { \ + public: \ + Class(const char *path, \ + const char *function, \ + int line, \ + const std::string & message = std::string()) : \ + Base(path, function, line, message) \ + { \ + m_className = #Class; \ + m_param = Param; \ + } \ + \ + Class(const char *path, \ + const char *function, \ + int line, \ + const Exception &reason, \ + const std::string & message = std::string()) : \ + Base(path, function, line, reason, message) \ + { \ + m_className = #Class; \ + m_param = Param; \ + } \ + \ + virtual int getParam() const \ + { \ + return m_param; \ + } \ + protected: \ + int m_param; \ + }; + +#define DECLARE_JOB_EXCEPTION(Base, Class, Param) \ + class Class : \ + public Base { \ + public: \ + Class(const char *path, \ + const char *function, \ + int line, \ + const std::string & message = std::string()) : \ + Base(path, function, line, message) \ + { \ + m_className = #Class; \ + m_param = Param; \ + } \ + \ + Class(const char *path, \ + const char *function, \ + int line, \ + const Exception &reason, \ + const std::string & message = std::string()) : \ + Base(path, function, line, reason, message) \ + { \ + m_className = #Class; \ + m_param = Param; \ + } \ + \ + virtual int getParam() const \ + { \ + return m_param; \ + } \ + }; + +namespace Jobs { +DECLARE_JOB_EXCEPTION_BASE(DPL::Exception, JobExceptionBase, 0) +} + +#endif /* SRC_INSTALLER_CORE_JOBS_JOB_EXCEPTION_BASE_H_ */ diff --git a/src_wearable/jobs/job_exception_error.h b/src_wearable/jobs/job_exception_error.h new file mode 100644 index 0000000..1caba99 --- /dev/null +++ b/src_wearable/jobs/job_exception_error.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file job_exception_error.h + * @author Soyoung Kim (sy037.kim@samsung.com) + * @version 1.0 + * @brief This file contains declarations of wrt api + */ + +/* + * @defgroup wrt_engine_group WebRunTime engine Library + * @ingroup internet_FW + * Functions to APIs to access wrt-engine + */ + +#ifndef JOB_EXCEPTION_ERROR_H +#define JOB_EXCEPTION_ERROR_H + +#include +#include + +namespace Jobs { +namespace Exceptions { +enum Type +{ + Success = 0, ///< Success + + /* pkgmgr error */ + ErrorPackageNotFound, ///< + ErrorPackageInvalid, ///< invalid widget package + ErrorPackageLowerVersion, ///< given version is lower + ErrorPackageExecutableNotFound, + + ErrorManifestNotFound = 11, ///< + ErrorManifestInvalid, ///< + ErrorConfigNotFound, ///< couldn't find config.xml + ErrorConfigInvalid, ///< invalid config.xml + + ErrorSignatureNotFound = 21, ///< signature file not exist. + ErrorSignatureInvalid, ///< invalid signature file + ErrorSignatureVerificationFailed, ///< failure in verificate + ///< signature + ErrorRootCertificateNotFound = 31, ///< couldn't find root + ErrorCertificationInvaid, ///< invalid certification + ErrorCertificateChainVerificationFailed, ///< failure in verificate + ErrorCertificateExpired, ///< expire cerification. + + ErrorInvalidPrivilege = 41, ///< invalid privilege. + ErrorPrivilegeLevelViolation, + + ErrorMenuIconNotFound = 51, ///< + + ErrorFatalError = 61, ///< failure in db operation + ErrorOutOfStorage, ///< failure in shortage of memory + ErrorOutOfMemory, ///< failure in shortage of RAM + ErrorArgumentInvalid, + + /* wrt-installer error */ + /* 121-140 : reserved for Web installer */ + ErrorPackageAlreadyInstalled = 121, ///< package already in target. + ErrorAceCheckFailed, ///< failure in ace check. + ErrorManifestCreateFailed, ///< failure in creating manifest + ErrorEncryptionFailed, ///< failure in encryption resource + ErrorInstallOspServcie, ///< Failure in installing osp service + ErrorPluginInstallationFailed, ///< failure in plugin installation + ErrorWidgetUninstallationFailed, ///< failure in uninstallation + ErrorNotSupportRDSUpdate, ///< failure in rds update + + ErrorUnknown = 140, ///< do not use this error code. +}; +} +} + +#endif /* JOB_EXCEPTION_ERROR_H */ diff --git a/src_wearable/jobs/job_types.h b/src_wearable/jobs/job_types.h new file mode 100644 index 0000000..5f845bf --- /dev/null +++ b/src_wearable/jobs/job_types.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file job_types.h + * @author Tomasz Iwanek () + */ +#ifndef JOB_TYPES_H +#define JOB_TYPES_H + +namespace Jobs { +/** + * @brief Defines installation and uninstallation type. + */ +enum InstallationType +{ + UnknownInstallation, ///< defines installation of yet unknown type + NewInstallation, ///< defines install process + UpdateInstallation, ///< defines update installation + Uninstallation, ///< defines uninstall process + PluginInstallation ///< defines plugin installation process +}; + +} + +#endif // JOB_TYPES_H diff --git a/src_wearable/jobs/plugin_install/job_plugin_install.cpp b/src_wearable/jobs/plugin_install/job_plugin_install.cpp new file mode 100755 index 0000000..36a5d83 --- /dev/null +++ b/src_wearable/jobs/plugin_install/job_plugin_install.cpp @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file job_plugin_install.cpp + * @author Pawel Sikorski (p.sikorski@samgsung.com) + * @version + * @brief + */ +#include +#include +#include "plugin_objects.h" +#include +#include + +namespace Jobs { +namespace PluginInstall { +JobPluginInstall::JobPluginInstall(PluginPath const &pluginPath, + const PluginInstallerStruct &installerStruct) + : + Job(PluginInstallation), + JobContextBase(installerStruct), + m_exceptionCaught(Jobs::Exceptions::Success) +{ + // + // Init installer context + // + m_context.pluginFilePath = pluginPath; + m_context.pluginHandle = INVALID_HANDLE; + m_context.installationCompleted = false; + + m_context.installerTask = this; + // + // Create main installation tasks + // + AddTask(new PluginInstallTask(&m_context)); +} + +void JobPluginInstall::SendProgress() +{ + if (GetProgressFlag() && GetInstallerStruct().progressCallback != NULL) { + _D("Call Plugin install progressCallback"); + GetInstallerStruct().progressCallback(GetInstallerStruct().userParam, + GetProgressPercent(), + GetProgressDescription()); + } +} + +void JobPluginInstall::SendFinishedSuccess() +{ + PluginHandle handle = getNewPluginHandle(); + + if (handle != Jobs::PluginInstall::JobPluginInstall::INVALID_HANDLE && + isReadyToInstall()) + { + _D("Call Plugin install success finishedCallback"); + GetInstallerStruct().finishedCallback(GetInstallerStruct().userParam, + Jobs::Exceptions::Success); + } else { + _D("Call Plugin install waiting finishedCallback"); + GetInstallerStruct().finishedCallback(GetInstallerStruct().userParam, + Jobs::Exceptions::ErrorPluginInstallationFailed); + + _D("Installation: %s NOT possible", getFilePath().c_str()); + } +} + +void JobPluginInstall::SendFinishedFailure() +{ + LOGE(COLOR_ERROR "Error in plugin installation step: %d" COLOR_END, m_exceptionCaught); + LOGE(COLOR_ERROR "Message: %s" COLOR_END, m_exceptionMessage.c_str()); + fprintf(stderr, "[Err:%d] %s", m_exceptionCaught, m_exceptionMessage.c_str()); + + _D("Call Plugin install failure finishedCallback"); + GetInstallerStruct().finishedCallback(GetInstallerStruct().userParam, + m_exceptionCaught); +} + +void JobPluginInstall::SaveExceptionData(const Jobs::JobExceptionBase &e) +{ + m_exceptionCaught = static_cast(e.getParam()); + m_exceptionMessage = e.GetMessage(); +} +} //namespace Jobs +} //namespace PluginInstall diff --git a/src_wearable/jobs/plugin_install/job_plugin_install.h b/src_wearable/jobs/plugin_install/job_plugin_install.h new file mode 100644 index 0000000..a8d3386 --- /dev/null +++ b/src_wearable/jobs/plugin_install/job_plugin_install.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file job_plugin_install.h + * @author Pawel Sikorski (p.sikorski@samgsung.com) + * @version + * @brief + */ + +#ifndef WRT_SRC_INSTALLER_CORE_JOB_JOB_PLUGIN_INSTALL_H_ +#define WRT_SRC_INSTALLER_CORE_JOB_JOB_PLUGIN_INSTALL_H_ + +//SYSTEM INCLUDES +#include + +//WRT INCLUDES +#include +#include +#include +#include +namespace Jobs { +namespace PluginInstall { +class JobPluginInstall : + public Job, + public JobProgressBase, + public JobContextBase +{ + public: + static const WrtDB::DbPluginHandle INVALID_HANDLE = -1; + + public: + /** + * @brief Automaticaly sets installation process + */ + JobPluginInstall(PluginPath const &pluginPath, + const PluginInstallerStruct &installerStruct); + + WrtDB::DbPluginHandle getNewPluginHandle() const + { + return m_context.pluginHandle; + } + std::string getFilePath() const + { + return m_context.pluginFilePath.Fullpath(); + } + bool isReadyToInstall() const + { + return m_context.installationCompleted; + } + + void SendProgress(); + void SendFinishedSuccess(); + void SendFinishedFailure(); + void SaveExceptionData(const Jobs::JobExceptionBase &e); + + private: + PluginInstallerContext m_context; + + //TODO move it to base class of all jobs + //maybe separate JobBase class for this? + Jobs::Exceptions::Type m_exceptionCaught; + std::string m_exceptionMessage; +}; +} //namespace Jobs +} //namespace PluginInstall + +#endif /* WRT_SRC_INSTALLER_CORE_JOB_JOB_PLUGIN_INSTALL_H_ */ diff --git a/src_wearable/jobs/plugin_install/plugin_install_task.cpp b/src_wearable/jobs/plugin_install/plugin_install_task.cpp new file mode 100644 index 0000000..5f42730 --- /dev/null +++ b/src_wearable/jobs/plugin_install/plugin_install_task.cpp @@ -0,0 +1,389 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file install_one_task.cpp + * @author Pawel Sikorski (p.sikorski@samgsung.com) + * @author Grzegorz Krawczyk (g.krawczyk@samgsung.com) + * @version + * @brief + */ + +//SYSTEM INCLUDES +#include +#include +#include + +//WRT INCLUDES +#include +#include +#include "plugin_install_task.h" +#include "job_plugin_install.h" +#include "plugin_installer_errors.h" +#include "plugin_metafile_reader.h" +#include +//#include +#include +#include +#include +#include "plugin_objects.h" +#include +#include +#include + +using namespace WrtDB; + +#define SET_PLUGIN_INSTALL_PROGRESS(step, desc) \ + m_context->installerTask->UpdateProgress( \ + PluginInstallerContext::step, desc); + +#define DISABLE_IF_PLUGIN_WITHOUT_LIB() \ + if (m_pluginInfo.m_libraryName.empty()) \ + { \ + _W("Plugin without library."); \ + return; \ + } + +namespace Jobs { +namespace PluginInstall { +PluginInstallTask::PluginInstallTask(PluginInstallerContext *inCont) : + DPL::TaskDecl(this), + m_context(inCont), + m_pluginHandle(0), + m_dataFromConfigXML(true) +{ + AddStep(&PluginInstallTask::stepCheckPluginPath); + AddStep(&PluginInstallTask::stepParseConfigFile); + AddStep(&PluginInstallTask::stepFindPluginLibrary); + AddStep(&PluginInstallTask::stepCheckIfAlreadyInstalled); + AddStep(&PluginInstallTask::stepLoadPluginLibrary); + AddStep(&PluginInstallTask::stepRegisterPlugin); + AddStep(&PluginInstallTask::stepRegisterFeatures); + AddStep(&PluginInstallTask::stepRegisterPluginObjects); + AddStep(&PluginInstallTask::stepResolvePluginDependencies); + + SET_PLUGIN_INSTALL_PROGRESS(START, "Installation initialized"); +} + +PluginInstallTask::~PluginInstallTask() +{} + +void PluginInstallTask::stepCheckPluginPath() +{ + _D("Plugin installation: step CheckPluginPath"); + + if(!m_context->pluginFilePath.Exists()){ + ThrowMsg(Exceptions::PluginPathFailed, + "No such path"); + } + + SET_PLUGIN_INSTALL_PROGRESS(PLUGIN_PATH, "Path to plugin verified"); +} + +void PluginInstallTask::stepParseConfigFile() +{ + _D("Plugin installation: step parse config file"); + + if(!m_context->pluginFilePath.getMetaFile().Exists()){ + m_dataFromConfigXML = false; + return; + } + + _D("Plugin Config file::%s", m_context->pluginFilePath.getMetaFile().Fullpath().c_str()); + + Try + { + PluginMetafileReader reader; + reader.initialize(m_context->pluginFilePath.getMetaFile()); + reader.read(m_pluginInfo); + + FOREACH(it, m_pluginInfo.m_featureContainer) + { + _D("Parsed feature : %s", it->m_name.c_str()); + FOREACH(devCap, it->m_deviceCapabilities) { + _D(" | DevCap : %s", (*devCap).c_str()); + } + } + + SET_PLUGIN_INSTALL_PROGRESS(PLUGIN_PATH, "Config file analyzed"); + } + Catch(ValidationCore::ParserSchemaException::Base) + { + _E("Error during file processing %s", m_context->pluginFilePath.getMetaFile().Fullpath().c_str()); + ThrowMsg(Exceptions::PluginMetafileFailed, + "Metafile error"); + } +} + +void PluginInstallTask::stepFindPluginLibrary() +{ + if (m_dataFromConfigXML) { + return; + } + _D("Plugin installation: step find plugin library"); + _D("Plugin .so: %s", m_context->pluginFilePath.getLibraryName().c_str()); + m_pluginInfo.m_libraryName = m_context->pluginFilePath.getLibraryName(); +} + +void PluginInstallTask::stepCheckIfAlreadyInstalled() +{ + if (PluginDAO::isPluginInstalled(m_pluginInfo.m_libraryName)) { + ThrowMsg(Exceptions::PluginAlreadyInstalled, + "Plugin already installed"); + } + + SET_PLUGIN_INSTALL_PROGRESS(PLUGIN_EXISTS_CHECK, "Check if plugin exist"); +} + +void PluginInstallTask::stepLoadPluginLibrary() +{ + _D("Plugin installation: step load library"); + + DISABLE_IF_PLUGIN_WITHOUT_LIB() + + _D("Loading plugin: %s", m_context->pluginFilePath.getLibraryName().c_str()); + + fprintf(stderr, " - Try to dlopen() : [%s] ", m_context->pluginFilePath.getLibraryPath().Fullpath().c_str()); + + void *dlHandle = dlopen( m_context->pluginFilePath.getLibraryPath().Fullpath().c_str(), RTLD_LAZY); + if (dlHandle == NULL) { + const char* error = (const char*)dlerror(); + fprintf(stderr, + "-> Failed!\n %s\n", + (error != NULL ? error : "unknown")); + _E("Failed to load plugin: %s. Reason: %s", + m_context->pluginFilePath.getLibraryName().c_str(), (error != NULL ? error : "unknown")); + ThrowMsg(Exceptions::PluginLibraryError, "Library error"); + } + + fprintf(stderr, "-> Done.\n"); + + const js_entity_definition_t *rawEntityList = NULL; + get_widget_entity_map_proc *getWidgetEntityMapProcPtr = NULL; + + getWidgetEntityMapProcPtr = + reinterpret_cast(dlsym(dlHandle, + PLUGIN_GET_CLASS_MAP_PROC_NAME)); + + if (getWidgetEntityMapProcPtr) { + rawEntityList = (*getWidgetEntityMapProcPtr)(); + } else { + rawEntityList = + static_cast(dlsym(dlHandle, + PLUGIN_CLASS_MAP_NAME)); + } + + if (rawEntityList == NULL) { + dlclose(dlHandle); + _E("Failed to read class name %s", m_context->pluginFilePath.getLibraryName().c_str()); + ThrowMsg(Exceptions::PluginLibraryError, "Library error"); + } + + if (!m_dataFromConfigXML) { + on_widget_init_proc *onWidgetInitProc = + reinterpret_cast( + dlsym(dlHandle, PLUGIN_WIDGET_INIT_PROC_NAME)); + + if (NULL == onWidgetInitProc) { + dlclose(dlHandle); + _E("Failed to read onWidgetInit symbol %s", m_context->pluginFilePath.getLibraryName().c_str()); + ThrowMsg(Exceptions::PluginLibraryError, "Library error"); + } + + // obtain feature -> dev-cap mapping + feature_mapping_interface_t mappingInterface = { NULL, NULL, NULL }; + (*onWidgetInitProc)(&mappingInterface); + + if (!mappingInterface.featGetter || !mappingInterface.release || + !mappingInterface.dcGetter) + { + _E("Failed to obtain mapping interface from .so"); + ThrowMsg(Exceptions::PluginLibraryError, "Library error"); + } + + feature_mapping_t* devcapMapping = mappingInterface.featGetter(); + + _D("Getting mapping from features to device capabilities"); + + for (size_t i = 0; i < devcapMapping->featuresCount; ++i) { + PluginMetafileData::Feature feature; + feature.m_name = devcapMapping->features[i].feature_name; + + _D("Feature: %s", feature.m_name.c_str()); + + const devcaps_t* dc = + mappingInterface.dcGetter( + devcapMapping, + devcapMapping->features[i]. + feature_name); + + if (dc) { + _D("devcaps count: %d", dc->devCapsCount); + + for (size_t j = 0; j < dc->devCapsCount; ++j) { + _D("devcap: %s", dc->deviceCaps[j]); + feature.m_deviceCapabilities.insert(dc->deviceCaps[j]); + } + } + + m_pluginInfo.m_featureContainer.insert(feature); + } + + mappingInterface.release(devcapMapping); + } + + m_libraryObjects = PluginObjectsPtr(new PluginObjects()); + const js_entity_definition_t *rawEntityListIterator = rawEntityList; + + _D("#####"); + _D("##### Plugin: %s supports new plugin API", + m_context->pluginFilePath.getLibraryName().c_str()); + _D("#####"); + + while (rawEntityListIterator->parent_name != NULL && + rawEntityListIterator->object_name != NULL) + { + _D("##### [%s]: ", rawEntityListIterator->object_name); + _D("##### Parent: %s", rawEntityListIterator->parent_name); + _D("#####"); + + m_libraryObjects->addObjects(rawEntityListIterator->parent_name, + rawEntityListIterator->object_name); + + ++rawEntityListIterator; + } + + // Unload library + if (dlclose(dlHandle) != 0) { + _E("Cannot close plugin handle"); + } else { + _D("Library is unloaded"); + } + + // Load export table + _D("Library successfuly loaded and parsed"); + + SET_PLUGIN_INSTALL_PROGRESS(LOADING_LIBRARY, "Library loaded and analyzed"); +} + +void PluginInstallTask::stepRegisterPlugin() +{ + _D("Plugin installation: step register Plugin"); + + m_pluginHandle = + PluginDAO::registerPlugin(m_pluginInfo, m_context->pluginFilePath.Fullpath()); + + SET_PLUGIN_INSTALL_PROGRESS(REGISTER_PLUGIN, "Plugin registered"); +} + +void PluginInstallTask::stepRegisterFeatures() +{ + _D("Plugin installation: step register features"); + + FOREACH(it, m_pluginInfo.m_featureContainer) + { + _D("PluginHandle: %d", m_pluginHandle); + FeatureDAO::RegisterFeature(*it, m_pluginHandle); + } + SET_PLUGIN_INSTALL_PROGRESS(REGISTER_FEATURES, "Features registered"); +} + +void PluginInstallTask::stepRegisterPluginObjects() +{ + _D("Plugin installation: step register objects"); + + DISABLE_IF_PLUGIN_WITHOUT_LIB() + + //register implemented objects + PluginObjects::ObjectsPtr objects = + m_libraryObjects->getImplementedObject(); + + FOREACH(it, *objects) + { + PluginDAO::registerPluginImplementedObject(*it, m_pluginHandle); + } + + //register requiredObjects + objects = m_libraryObjects->getDependentObjects(); + + FOREACH(it, *objects) + { + if (m_libraryObjects->hasObject(*it)) { + _D("Dependency from the same library. ignored"); + continue; + } + + PluginDAO::registerPluginRequiredObject(*it, m_pluginHandle); + } + + SET_PLUGIN_INSTALL_PROGRESS(REGISTER_OBJECTS, "Plugin Objects registered"); +} + +void PluginInstallTask::stepResolvePluginDependencies() +{ + _D("Plugin installation: step resolve dependencies "); + + //DISABLE_IF_PLUGIN_WITHOUT_LIB + if (m_pluginInfo.m_libraryName.empty()) { + PluginDAO::setPluginInstallationStatus( + m_pluginHandle, + PluginDAO:: + INSTALLATION_COMPLETED); + //Installation completed + m_context->pluginHandle = m_pluginHandle; + m_context->installationCompleted = true; + _W("Plugin without library."); + return; + } + + PluginHandleSetPtr handles = PluginHandleSetPtr(new PluginHandleSet); + + DbPluginHandle handle = INVALID_PLUGIN_HANDLE; + + //register requiredObjects + FOREACH(it, *(m_libraryObjects->getDependentObjects())) + { + if (m_libraryObjects->hasObject(*it)) { + _D("Dependency from the same library. ignored"); + continue; + } + + handle = PluginDAO::getPluginHandleForImplementedObject(*it); + if (handle == INVALID_PLUGIN_HANDLE) { + _E("Library implementing: %s NOT FOUND", (*it).c_str()); + PluginDAO::setPluginInstallationStatus( + m_pluginHandle, + PluginDAO::INSTALLATION_WAITING); + return; + } + + handles->insert(handle); + } + + PluginDAO::registerPluginLibrariesDependencies(m_pluginHandle, handles); + + PluginDAO::setPluginInstallationStatus(m_pluginHandle, + PluginDAO::INSTALLATION_COMPLETED); + + //Installation completed + m_context->pluginHandle = m_pluginHandle; + m_context->installationCompleted = true; + + SET_PLUGIN_INSTALL_PROGRESS(RESOLVE_DEPENDENCIES, "Dependencies resolved"); +} + +#undef SET_PLUGIN_INSTALL_PROGRESS +} //namespace Jobs +} //namespace PluginInstall diff --git a/src_wearable/jobs/plugin_install/plugin_install_task.h b/src_wearable/jobs/plugin_install/plugin_install_task.h new file mode 100644 index 0000000..c7a5d8c --- /dev/null +++ b/src_wearable/jobs/plugin_install/plugin_install_task.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file install.h + * @author Pawel Sikorski (p.sikorski@samgsung.com) + * @author Grzegorz Krawczyk (g.krawczyk@samgsung.com) + * @version + * @brief + */ + +#ifndef INSTALL_H_ +#define INSTALL_H_ + +//WRT INCLUDES +#include +#include "plugin_installer_context.h" +#include "plugin_objects.h" + +namespace Jobs { +namespace PluginInstall { +class PluginInstallTask : + public DPL::TaskDecl +{ + public: + PluginInstallTask(PluginInstallerContext *inCont); + virtual ~PluginInstallTask(); + + private: + //data + PluginInstallerContext *m_context; + + //PluginMetafile + WrtDB::PluginMetafileData m_pluginInfo; + + //Plugin LibraryObjects + PluginObjectsPtr m_libraryObjects; + + WrtDB::DbPluginHandle m_pluginHandle; + + bool m_dataFromConfigXML; + + //steps + void stepCheckPluginPath(); + void stepFindPluginLibrary(); + void stepParseConfigFile(); + void stepCheckIfAlreadyInstalled(); + void stepLoadPluginLibrary(); + void stepRegisterPlugin(); + void stepRegisterFeatures(); + void stepRegisterPluginObjects(); + void stepResolvePluginDependencies(); +}; +} //namespace Jobs +} //namespace PluginInstall + +#endif /* INSTALL_H_ */ diff --git a/src_wearable/jobs/plugin_install/plugin_installer_context.h b/src_wearable/jobs/plugin_install/plugin_installer_context.h new file mode 100644 index 0000000..1efd504 --- /dev/null +++ b/src_wearable/jobs/plugin_install/plugin_installer_context.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file plugin_installer_structs.h + * @author Pawel Sikorski (p.sikorski@samgsung.com) + * @version + * @brief Definition file of plugin installer tasks data structures + */ +#ifndef WRT_SRC_INSTALLERCORE_PLUGININSTALLERTASKS_PLUGININSTALLERCONTEXT_H_ +#define WRT_SRC_INSTALLERCORE_PLUGININSTALLERTASKS_PLUGININSTALLERCONTEXT_H_ + +#include +#include +#include +//#include + +using namespace WrtDB; + +namespace Jobs { +namespace PluginInstall { +class JobPluginInstall; +} +} + +struct PluginInstallerContext +{ + enum PluginInstallStep + { + START, + PLUGIN_PATH, + CONFIG_FILE, + PLUGIN_EXISTS_CHECK, + LOADING_LIBRARY, + REGISTER_PLUGIN, + REGISTER_FEATURES, + REGISTER_OBJECTS, + RESOLVE_DEPENDENCIES, + PLUGIN_INSTALL_END + }; + + PluginPath pluginFilePath; ///< plugin directory + PluginPath metaFilePath; + bool m_dataFromConfigXML; + WrtDB::DbPluginHandle pluginHandle; + // if this value is true the plugin model may be created + // if not plugin installation has failed from some reason + bool installationCompleted; + + //used to set installation progress + Jobs::PluginInstall::JobPluginInstall* installerTask; +}; +#endif // WRT_SRC_INSTALLERCORE_PLUGININSTALLERTASKS_PLUGININSTALLERCONTEXT_H_ diff --git a/src_wearable/jobs/plugin_install/plugin_installer_errors.h b/src_wearable/jobs/plugin_install/plugin_installer_errors.h new file mode 100644 index 0000000..11c7f88 --- /dev/null +++ b/src_wearable/jobs/plugin_install/plugin_installer_errors.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file plugin_installer_errors.h + * @author Pawel Sikorski (p.sikorski@samgsung.com) + * @author Grzegorz Krawczyk (g.krawczyk@samgsung.com) + * @version + * @brief + */ + +#ifndef \ + WRT_SRC_INSTALLER_CORE_PLUGIN_INSTALLER_TASKS_PLUGIN_INSTALLER_ERRORS_H_ +#define \ + WRT_SRC_INSTALLER_CORE_PLUGIN_INSTALLER_TASKS_PLUGIN_INSTALLER_ERRORS_H_ + +#include +#include + +using namespace Jobs::Exceptions; + +namespace Jobs { +namespace PluginInstall { +namespace Exceptions { + +DECLARE_JOB_EXCEPTION_BASE(JobExceptionBase, Base, ErrorUnknown) +DECLARE_JOB_EXCEPTION(Base, PluginPathFailed, ErrorPluginInstallationFailed) +DECLARE_JOB_EXCEPTION(Base, PluginMetafileFailed, ErrorPluginInstallationFailed) +DECLARE_JOB_EXCEPTION(Base, PluginAlreadyInstalled, + ErrorPluginInstallationFailed) +DECLARE_JOB_EXCEPTION(Base, PluginLibraryError, ErrorPluginInstallationFailed) +DECLARE_JOB_EXCEPTION(Base, InstallationWaitingError, + ErrorPluginInstallationFailed) +DECLARE_JOB_EXCEPTION(Base, UnknownError, ErrorUnknown) +} //namespace +} //namespace +} //namespace + +#endif +//WRT_SRC_INSTALLER_CORE_PLUGIN_INSTALLER_TASKS_PLUGIN_INSTALLER_ERRORS_H_ + diff --git a/src_wearable/jobs/plugin_install/plugin_installer_struct.h b/src_wearable/jobs/plugin_install/plugin_installer_struct.h new file mode 100644 index 0000000..c253897 --- /dev/null +++ b/src_wearable/jobs/plugin_install/plugin_installer_struct.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file plugin_installer_struct.h + * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com) + * @author Grzegorz Krawczyk (g.krawczyk@samsung.com) + * @version 1.0 + * @brief Implementation file for widget installer struct + */ +#ifndef WRT_SRC_INSTALLER_CORE_PLUGIN_INSTALLER_PLUGIN_INSTALLER_STRUCT_H_ +#define WRT_SRC_INSTALLER_CORE_PLUGIN_INSTALLER_PLUGIN_INSTALLER_STRUCT_H_ + +#include +#include + +//Plugin Installer typedefs +typedef void (*PluginInstallerFinishedCallback)( + void *userParam, + Jobs::Exceptions::Type); + +//installer progress +typedef void (*PluginInstallerProgressCallback)( + void *userParam, + ProgressPercent percent, + const ProgressDescription &description); + +//Plugin Installetion Struct +typedef Jobs::JobCallbacksBase +PluginInstallerStruct; + +#endif // WRT_SRC_INSTALLER_CORE_PLUGIN_INSTALLER_PLUGIN_INSTALLER_STRUCT_H_ diff --git a/src_wearable/jobs/plugin_install/plugin_metafile_reader.cpp b/src_wearable/jobs/plugin_install/plugin_metafile_reader.cpp new file mode 100644 index 0000000..c7df516 --- /dev/null +++ b/src_wearable/jobs/plugin_install/plugin_metafile_reader.cpp @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file plugin_metafile_reader.cpp + * @author Grzegorz Krawczyk(g.krawczyk@samsung.com) + * @version 1.0 + * @brief + */ + +#include "plugin_metafile_reader.h" +#include + +using namespace WrtDB; + +namespace { +const std::string XML_NAMESPACE = ""; + +const std::string TOKEN_LIBRARY_NAME = "library-name"; +const std::string TOKEN_API_FEATURE = "api-feature"; +const std::string TOKEN_NAME = "name"; +const std::string TOKEN_DEVICECAPABILITY = "device-capability"; +} + +PluginMetafileReader::PluginMetafileReader() : m_parserSchema(this) +{ + m_parserSchema.addEndTagCallback( + TOKEN_LIBRARY_NAME, + XML_NAMESPACE, + &PluginMetafileReader::tokenEndLibraryName); + + m_parserSchema.addEndTagCallback( + TOKEN_API_FEATURE, + XML_NAMESPACE, + &PluginMetafileReader::tokenEndApiFeature); + + m_parserSchema.addEndTagCallback( + TOKEN_NAME, + XML_NAMESPACE, + &PluginMetafileReader::tokenEndName); + + m_parserSchema.addEndTagCallback( + TOKEN_DEVICECAPABILITY, + XML_NAMESPACE, + &PluginMetafileReader::tokenEndDeviceCapability); +} + +void PluginMetafileReader::initialize(const PluginPath &filename) +{ + m_parserSchema.initialize(filename.Fullpath(), + true, + ValidationCore::SaxReader::VALIDATION_DTD, + std::string()); +} + +void PluginMetafileReader::read(WrtDB::PluginMetafileData &data) +{ + m_parserSchema.read(data); +} + +void PluginMetafileReader::blankFunction(PluginMetafileData & /* data */) +{} + +void PluginMetafileReader::tokenEndLibraryName(PluginMetafileData &data) +{ + data.m_libraryName = m_parserSchema.getText(); +} + +void PluginMetafileReader::tokenEndApiFeature(PluginMetafileData &data) +{ + data.m_featureContainer.insert(m_feature); + m_feature.m_deviceCapabilities.clear(); +} + +void PluginMetafileReader::tokenEndName(PluginMetafileData & /* data */) +{ + m_feature.m_name = m_parserSchema.getText(); +} + +void PluginMetafileReader::tokenEndDeviceCapability(PluginMetafileData& /*data*/) +{ + m_feature.m_deviceCapabilities.insert(m_parserSchema.getText()); +} + diff --git a/src_wearable/jobs/plugin_install/plugin_metafile_reader.h b/src_wearable/jobs/plugin_install/plugin_metafile_reader.h new file mode 100644 index 0000000..a3a3068 --- /dev/null +++ b/src_wearable/jobs/plugin_install/plugin_metafile_reader.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file plugin_metafile_reader.h + * @author Grzegorz Krawczyk(g.krawczyk@samsung.com) + * @version 1.0 + * @brief + */ + +#ifndef WRT_SRC_INSTALLER_CORE_PLUGIN_INSTALLER_TASKS_PLUGIN_METAFILE_READER_H_ +#define WRT_SRC_INSTALLER_CORE_PLUGIN_INSTALLER_TASKS_PLUGIN_METAFILE_READER_H_ + +#include +#include + +class PluginPath; + +class PluginMetafileReader +{ + public: + PluginMetafileReader(); + + void initialize(const PluginPath &filename); + + void read(WrtDB::PluginMetafileData &data); + + private: + void blankFunction(WrtDB::PluginMetafileData &data); + + void tokenEndLibraryName(WrtDB::PluginMetafileData &data); + void tokenEndApiFeature(WrtDB::PluginMetafileData &data); + void tokenEndName(WrtDB::PluginMetafileData &data); + void tokenEndDeviceCapability(WrtDB::PluginMetafileData &data); + + WrtDB::PluginMetafileData::Feature m_feature; + + ValidationCore::ParserSchema m_parserSchema; +}; + +#endif diff --git a/src_wearable/jobs/plugin_install/plugin_objects.cpp b/src_wearable/jobs/plugin_install/plugin_objects.cpp new file mode 100644 index 0000000..9235f47 --- /dev/null +++ b/src_wearable/jobs/plugin_install/plugin_objects.cpp @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file plugin_objects.h + * @author Grzegorz Krawczyk (g.krawczyk@samgsung.com) + * @version + * @brief + */ +#include +#include +#include "plugin_objects.h" + +namespace { +const char* SEPARATOR = "."; +const std::string GLOBAL_OBJECT_NAME = "GLOBAL_OBJECT"; + +std::string normalizeName(const std::string& objectName) +{ + if (objectName.empty()) { + _E("Normalize name, name size is 0"); + return objectName; + } + + if (!objectName.compare(0, GLOBAL_OBJECT_NAME.size(), + GLOBAL_OBJECT_NAME)) + { + return objectName; + } + + //each object in storage has name started from $GLOBAL_OBJECT_NAME$ + return GLOBAL_OBJECT_NAME + std::string(SEPARATOR) + objectName; +} + +std::string normalizeName(const std::string& objectName, + const std::string& parentName) +{ + if (objectName.empty() || parentName.empty()) { + _E("Normalize name, name size or parent name size is 0"); + return std::string(); + } + + std::string normalizedName; + normalizedName = normalizeName(parentName) + + std::string(SEPARATOR) + objectName; + + return normalizedName; +} +} + +PluginObjects::PluginObjects() +{ + m_implemented = ObjectsPtr(new Objects()); + m_dependent = ObjectsPtr(new Objects()); +} + +PluginObjects::ObjectsPtr PluginObjects::getImplementedObject() const +{ + return m_implemented; +} + +PluginObjects::ObjectsPtr PluginObjects::getDependentObjects() const +{ + return m_dependent; +} + +void PluginObjects::addObjects(const std::string& parentName, + const std::string& name) +{ + addImplementedObject(normalizeName(name, parentName)); + addDependentObject(normalizeName(parentName)); +} + +void PluginObjects::addDependentObject(const std::string& value) +{ + if (!value.compare(GLOBAL_OBJECT_NAME)) { + //dont add dependency to GLOBAL_OBJECT + return; + } + m_dependent->insert(value); +} + +bool PluginObjects::hasObject(const std::string& name) const +{ + return m_implemented->find(name) != m_implemented->end(); +} + +void PluginObjects::addImplementedObject(const std::string& value) +{ + m_implemented->insert(value); +} diff --git a/src_wearable/jobs/plugin_install/plugin_objects.h b/src_wearable/jobs/plugin_install/plugin_objects.h new file mode 100644 index 0000000..0b27a14 --- /dev/null +++ b/src_wearable/jobs/plugin_install/plugin_objects.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file plugin_objects.h + * @author Grzegorz Krawczyk(g.krawczyk@samsung.com) + * @version 1.0 + * @brief + */ + +#ifndef WRT_SRC_INSTALLER_CORE_PLUGIN_INSTALLER_TASKS_PLUGIN_OBJECTS_H_ +#define WRT_SRC_INSTALLER_CORE_PLUGIN_INSTALLER_TASKS_PLUGIN_OBJECTS_H_ + +#include +#include +#include +#include + +#include +//TODO TO BE MOVED SOMEWHERE ELSE +// AS OTHER MODULES (LIKE DAO) USE IT + +class PluginObjects : public WrtDB::PluginObjectsDAO +{ + public: + explicit PluginObjects(); + + //getters for objects from library + ObjectsPtr getImplementedObject() const; + ObjectsPtr getDependentObjects() const; + + //add object declaration + void addObjects(const std::string& parentName, + const std::string& name); + + //check if library implemements object given as name + bool hasObject(const std::string& name) const; + + private: + void addImplementedObject(const std::string& value); + void addDependentObject(const std::string& value); +}; + +typedef std::shared_ptr PluginObjectsPtr; + +#endif diff --git a/src_wearable/jobs/widget_install/ace_registration.cpp b/src_wearable/jobs/widget_install/ace_registration.cpp new file mode 100644 index 0000000..31df490 --- /dev/null +++ b/src_wearable/jobs/widget_install/ace_registration.cpp @@ -0,0 +1,251 @@ +/* + * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file ace_registration.cpp + * @author Andrzej Surdej (a.surdej@gmail.com) + * @version 1.0 + * @brief Translate structures to ace api - implementation file + */ + +#include +#include +#include +#include + +#include + +namespace { +char* toAceString(const DPL::OptionalString& os) +{ + if (!!os) { + return strdup(DPL::ToUTF8String(*os).c_str()); + } else { + return NULL; + } +} + +char* toAceString(const std::string& str) +{ + if (!str.empty()) { + return strdup(str.c_str()); + } else { + return NULL; + } +} +} //anonymous namespace + +namespace AceApi { +bool registerAceWidget(const WrtDB::DbWidgetHandle& widgetHandle, + const WrtDB::WidgetRegisterInfo& widgetConfig, + const WrtDB::WidgetCertificateDataList& certList) +{ + _D("Updating Ace database"); + struct widget_info wi; + + switch (widgetConfig.webAppType.appType) { + case WrtDB::APP_TYPE_TIZENWEBAPP: + wi.type = Tizen; + break; + default: + _E("Unknown application type"); + return false; + } + + wi.id = toAceString(widgetConfig.configInfo.widget_id); + wi.version = toAceString(widgetConfig.configInfo.version); + wi.author = toAceString(widgetConfig.configInfo.authorName); + // TODO: Need to remove "shareHref" from "widget_info" in wrt-security + wi.shareHerf = NULL; + _D("Basic data converted. Certificates begin."); + + //one more element for NULL termination + _D("Found: %d certificates", certList.size()); + ace_certificate_data** certData = new ace_certificate_data * + [certList.size() + 1]; + certData[certList.size()] = NULL; // last element set to NULL + + int i = 0; + FOREACH(it, certList) + { + certData[i] = new ace_certificate_data; + switch (it->owner) { + case WrtDB::WidgetCertificateData::AUTHOR: + certData[i]->owner = AUTHOR; + break; + case WrtDB::WidgetCertificateData::DISTRIBUTOR: + certData[i]->owner = DISTRIBUTOR; + break; + default: + _D("Unknown owner type of cert"); + certData[i]->owner = UNKNOWN; + break; + } + switch (it->type) { + case WrtDB::WidgetCertificateData::ENDENTITY: + certData[i]->type = ENDENTITY; + break; + case WrtDB::WidgetCertificateData::ROOT: + certData[i]->type = ROOT; + break; + default: + _E("Unknown type of cert"); + certData[i]->type = ENDENTITY; + break; + } + certData[i]->chain_id = it->chainId; + + certData[i]->md5_fp = toAceString(it->strMD5Fingerprint); + certData[i]->sha1_fp = toAceString(it->strSHA1Fingerprint); + certData[i]->common_name = + toAceString(DPL::ToUTF8String(it->strCommonName)); + ++i; + } + + _D("Registerign widget in ace"); + ace_return_t retval = ace_register_widget( + static_cast(widgetHandle), &wi, certData); + + //clean up - WidgetInfo + free(wi.author); + free(wi.id); + free(wi.version); + + //free cert list + i = 0; + while (certData[i] != NULL) { + free(certData[i]->common_name); + free(certData[i]->md5_fp); + free(certData[i]->sha1_fp); + delete certData[i]; + ++i; + } + delete[] certData; + return retval == ACE_OK; +} +bool registerAceWidgetFromDB(const WrtDB::DbWidgetHandle& widgetHandle) +{ + using namespace WrtDB; + _D("Updating Ace database from Widget DB"); + struct widget_info wi; + DPL::OptionalString os; + WrtDB::WidgetCertificateDataList certList; + + wi.id = NULL; + wi.version = NULL; + wi.author = NULL; + wi.shareHerf = NULL; + + Try { + WidgetDAOReadOnly dao(widgetHandle); + + WidgetType type = dao.getWidgetType(); + if (type == WrtDB::APP_TYPE_TIZENWEBAPP) { + wi.type = Tizen; + } else { + _E("Unknown application type"); + return false; + } + + wi.id = toAceString(dao.getGUID()); + wi.version = toAceString(dao.getVersion()); + wi.author = toAceString(dao.getAuthorName()); + // TODO: Need to remove "shareHref" from "widget_info" in wrt-security + wi.shareHerf = NULL; + _D("Basic data converted. Certificates begin."); + certList = dao.getCertificateDataList(); + } + Catch(WidgetDAOReadOnly::Exception::WidgetNotExist) { + _E("Widget does not exist"); + if(wi.id != NULL) { + free(wi.id); + } + if(wi.version != NULL) { + free(wi.version); + } + if(wi.author != NULL) { + free(wi.author); + } + if(wi.shareHerf != NULL) { + free(wi.shareHerf); + } + return false; + } + + //one more element for NULL termination + _D("Found: %d certificates", certList.size()); + ace_certificate_data** certData = new ace_certificate_data * + [certList.size() + 1]; + certData[certList.size()] = NULL; // last element set to NULL + + int i = 0; + FOREACH(it, certList) + { + certData[i] = new ace_certificate_data; + switch (it->owner) { + case WrtDB::WidgetCertificateData::AUTHOR: + certData[i]->owner = AUTHOR; + break; + case WrtDB::WidgetCertificateData::DISTRIBUTOR: + certData[i]->owner = DISTRIBUTOR; + break; + default: + _D("Unknown owner type of cert"); + certData[i]->owner = UNKNOWN; + break; + } + switch (it->type) { + case WrtDB::WidgetCertificateData::ENDENTITY: + certData[i]->type = ENDENTITY; + break; + case WrtDB::WidgetCertificateData::ROOT: + certData[i]->type = ROOT; + break; + default: + _E("Unknown type of cert"); + certData[i]->type = ENDENTITY; + break; + } + certData[i]->chain_id = it->chainId; + + certData[i]->md5_fp = toAceString(it->strMD5Fingerprint); + certData[i]->sha1_fp = toAceString(it->strSHA1Fingerprint); + certData[i]->common_name = + toAceString(DPL::ToUTF8String(it->strCommonName)); + ++i; + } + + _D("Registerign widget in ace"); + ace_return_t retval = ace_register_widget( + static_cast(widgetHandle), &wi, certData); + + //clean up - WidgetInfo + free(wi.author); + free(wi.id); + free(wi.version); + + //free cert list + i = 0; + while (certData[i] != NULL) { + free(certData[i]->common_name); + free(certData[i]->md5_fp); + free(certData[i]->sha1_fp); + delete certData[i]; + ++i; + } + delete[] certData; + return retval == ACE_OK; +} +} diff --git a/src_wearable/jobs/widget_install/ace_registration.h b/src_wearable/jobs/widget_install/ace_registration.h new file mode 100644 index 0000000..f98c3ce --- /dev/null +++ b/src_wearable/jobs/widget_install/ace_registration.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file ace_registration.h + * @author Andrzej Surdej (a.surdej@gmail.com) + * @version 1.0 + * @brief Translate structures to ace api - header file + */ +#ifndef WRT_SRC_INSTALLER_CORE_ACE_REGISTRATION_H_ +#define WRT_SRC_INSTALLER_CORE_ACE_REGISTRATION_H_ + +#include + +namespace AceApi { +bool registerAceWidget(const WrtDB::DbWidgetHandle& widgetHandle, + const WrtDB::WidgetRegisterInfo& widgetConfig, + const WrtDB::WidgetCertificateDataList& certList); +bool registerAceWidgetFromDB(const WrtDB::DbWidgetHandle& widgetHandle); +} + +#endif /* WRT_SRC_INSTALLER_CORE_ACE_REGISTRATION_H_ */ + diff --git a/src_wearable/jobs/widget_install/directory_api.cpp b/src_wearable/jobs/widget_install/directory_api.cpp new file mode 100644 index 0000000..63532ec --- /dev/null +++ b/src_wearable/jobs/widget_install/directory_api.cpp @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file directory_api.cpp + * @author Soyoung Kim(sy037.kim@samsung.com) + * @version 1.0 + * @brief directory api - implementation file + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace DirectoryApi { +bool DirectoryCopy(std::string source, std::string dest) +{ + DIR* dir = opendir(source.c_str()); + if (NULL == dir) { + return false; + } + + struct dirent dEntry; + struct dirent *dEntryResult; + int return_code; + + do { + struct stat statInfo; + return_code = readdir_r(dir, &dEntry, &dEntryResult); + if (dEntryResult != NULL && return_code == 0) { + std::string fileName = dEntry.d_name; + std::string fullName = source + "/" + fileName; + + if (stat(fullName.c_str(), &statInfo) != 0) { + closedir(dir); + return false; + } + + if (S_ISDIR(statInfo.st_mode)) { + if (("." == fileName) || (".." == fileName)) { + continue; + } + std::string destFolder = dest + "/" + fileName; + WrtUtilMakeDir(destFolder); + + if (!DirectoryCopy(fullName, destFolder)) { + closedir(dir); + return false; + } + } + + std::string destFile = dest + "/" + fileName; + std::ifstream infile(fullName); + std::ofstream outfile(destFile); + outfile << infile.rdbuf(); + outfile.close(); + infile.close(); + + errno = 0; + if (-1 == chown(destFile.c_str(), + statInfo.st_uid, + statInfo.st_gid)) { + int error = errno; + _D("Failed to change owner [%s]", DPL::GetErrnoString(error).c_str()); + } + } + } while (dEntryResult != NULL && return_code == 0); + closedir(dir); + return true; +} +} diff --git a/src_wearable/jobs/widget_install/directory_api.h b/src_wearable/jobs/widget_install/directory_api.h new file mode 100644 index 0000000..1632528 --- /dev/null +++ b/src_wearable/jobs/widget_install/directory_api.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file directory_api.h + * @author Soyoung Kim(sy037.kim@samsung.com) + * @version 1.0 + * @brief directory api - header file + */ +#ifndef WRT_SRC_INSTALLER_CORE_DIRECTORY_API_H_ +#define WRT_SRC_INSTALLER_CORE_DIRECTORY_API_H_ + +#include + +namespace DirectoryApi { +bool DirectoryCopy(std::string source, std::string dest); +} + +#endif /* WRT_SRC_INSTALLER_CORE_DIRECTORY_API_H_ */ + diff --git a/src_wearable/jobs/widget_install/job_widget_install.cpp b/src_wearable/jobs/widget_install/job_widget_install.cpp new file mode 100644 index 0000000..14e01c5 --- /dev/null +++ b/src_wearable/jobs/widget_install/job_widget_install.cpp @@ -0,0 +1,402 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file job_widget_install.cpp + * @author Radoslaw Wicik r.wicik@samsung.com + * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com) + * @version 1.0 + * @brief Implementation file for main installer task + */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include "root_parser.h" +#include "widget_parser.h" +#include "parser_runner.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +using namespace WrtDB; +using namespace Jobs::Exceptions; + +namespace Jobs { +namespace WidgetInstall { + +JobWidgetInstall::JobWidgetInstall( + std::string const &widgetPath, + std::string const &tzPkgId, + const Jobs::WidgetInstall::WidgetInstallationStruct & + installerStruct) : + Job(UnknownInstallation), + JobContextBase(installerStruct), + m_exceptionCaught(Jobs::Exceptions::Success) +{ + m_installerContext.mode = m_jobStruct.m_installMode; + m_installerContext.requestedPath = widgetPath; + m_jobStruct.pkgmgrInterface->setPkgname(tzPkgId); + + if (InstallMode::Command::RECOVERY == m_installerContext.mode.command) { + m_installerContext.widgetConfig.tzPkgid = DPL::FromUTF8String(tzPkgId); + AddTask(new TaskRecovery(m_installerContext)); + } + + //start configuration of installation + AddTask(new TaskConfiguration(m_installerContext)); + + // Init installer context + m_installerContext.installStep = InstallerContext::INSTALL_START; + m_installerContext.job = this; + + m_installerContext.callerPkgId + = DPL::FromUTF8String(m_jobStruct.pkgmgrInterface->getCallerId()); + _D("Caller Package Id : %s", DPL::ToUTF8String(m_installerContext.callerPkgId).c_str()); +} + +void JobWidgetInstall::appendNewInstallationTaskList() +{ + _D("Configure installation succeeded"); + m_installerContext.job->SetProgressFlag(true); + + AddTask(new TaskFileManipulation(m_installerContext)); + AddTask(new TaskProcessConfig(m_installerContext)); + if (m_installerContext.widgetConfig.packagingType == + WrtDB::PKG_TYPE_HOSTED_WEB_APP) + { + AddTask(new TaskPrepareFiles(m_installerContext)); + } + AddTask(new TaskCertify(m_installerContext)); + AddTask(new TaskCertifyLevel(m_installerContext)); + AddTask(new TaskUserDataManipulation(m_installerContext)); + if (m_installerContext.needEncryption) { + AddTask(new TaskEncryptResource(m_installerContext)); + } + AddTask(new TaskManifestFile(m_installerContext)); + if (m_installerContext.widgetConfig.packagingType == + PKG_TYPE_HYBRID_WEB_APP) { + AddTask(new TaskInstallOspsvc(m_installerContext)); + } + AddTask(new TaskDatabase(m_installerContext)); + AddTask(new TaskAceCheck(m_installerContext)); + AddTask(new TaskSmack(m_installerContext)); + AddTask(new TaskPkgInfoUpdate(m_installerContext)); +} + +void JobWidgetInstall::appendUpdateInstallationTaskList() +{ + _D("Configure installation updated"); + _D("Widget Update"); + m_installerContext.job->SetProgressFlag(true); + AddTask(new TaskStatusCheck(m_installerContext)); + + if (m_installerContext.mode.command == + InstallMode::Command::REINSTALL) { + AddTask(new TaskPrepareReinstall(m_installerContext)); + } + + if (m_installerContext.mode.extension != + InstallMode::ExtensionType::DIR) { + AddTask(new TaskUpdateFiles(m_installerContext)); + AddTask(new TaskFileManipulation(m_installerContext)); + } + + AddTask(new TaskProcessConfig(m_installerContext)); + + if (m_installerContext.widgetConfig.packagingType == + WrtDB::PKG_TYPE_HOSTED_WEB_APP) { + AddTask(new TaskPrepareFiles(m_installerContext)); + } + + AddTask(new TaskCertify(m_installerContext)); + AddTask(new TaskCertifyLevel(m_installerContext)); + AddTask(new TaskUserDataManipulation(m_installerContext)); + if (m_installerContext.needEncryption) { + AddTask(new TaskEncryptResource(m_installerContext)); + } + AddTask(new TaskManifestFile(m_installerContext)); + if (m_installerContext.widgetConfig.packagingType == + PKG_TYPE_HYBRID_WEB_APP) { + AddTask(new TaskInstallOspsvc(m_installerContext)); + } + + AddTask(new TaskDatabase(m_installerContext)); + AddTask(new TaskAceCheck(m_installerContext)); + //TODO: remove widgetHandle from this task and move before database task + // by now widget handle is needed in ace check + // Any error in acecheck while update will break widget + AddTask(new TaskSmack(m_installerContext)); + AddTask(new TaskRemoveBackupFiles(m_installerContext)); + AddTask(new TaskPkgInfoUpdate(m_installerContext)); +} + +void JobWidgetInstall::appendRDSUpdateTaskList() +{ + _D("Configure installation RDS updated"); + m_installerContext.job->SetProgressFlag(true); + AddTask(new TaskStatusCheck(m_installerContext)); + AddTask(new TaskPrepareReinstall(m_installerContext)); + AddTask(new TaskCertify(m_installerContext)); +} + +void JobWidgetInstall::appendRecoveryTaskList() +{ + _D("Recovery Task"); + m_installerContext.job->SetProgressFlag(true); + + AddTask(new TaskProcessConfig(m_installerContext)); + + AddTask(new TaskCertify(m_installerContext)); + AddTask(new TaskCertifyLevel(m_installerContext)); + AddTask(new TaskManifestFile(m_installerContext)); + if (m_installerContext.widgetConfig.packagingType == + PKG_TYPE_HYBRID_WEB_APP) { + AddTask(new TaskInstallOspsvc(m_installerContext)); + } + AddTask(new TaskSmack(m_installerContext)); +} + +void JobWidgetInstall::appendFotaInstallationTaskList() +{ + /* TODO */ + _D("Configure installation succeeded"); + m_installerContext.job->SetProgressFlag(true); + + AddTask(new TaskProcessConfig(m_installerContext)); + AddTask(new TaskCertify(m_installerContext)); + AddTask(new TaskCertifyLevel(m_installerContext)); + AddTask(new TaskUserDataManipulation(m_installerContext)); + if (m_installerContext.needEncryption) { + AddTask(new TaskEncryptResource(m_installerContext)); + } + AddTask(new TaskManifestFile(m_installerContext)); + if (m_installerContext.widgetConfig.packagingType == + PKG_TYPE_HYBRID_WEB_APP) + { + AddTask(new TaskInstallOspsvc(m_installerContext)); + } + AddTask(new TaskDatabase(m_installerContext)); + AddTask(new TaskAceCheck(m_installerContext)); + AddTask(new TaskSmack(m_installerContext)); + AddTask(new TaskRemoveBackupFiles(m_installerContext)); + AddTask(new TaskPkgInfoUpdate(m_installerContext)); +} + +void JobWidgetInstall::appendFotaUpdateTaskList() +{ + _D("Configure installation updated"); + _D("Widget Update"); + m_installerContext.job->SetProgressFlag(true); + + AddTask(new TaskProcessConfig(m_installerContext)); + AddTask(new TaskCertify(m_installerContext)); + AddTask(new TaskCertifyLevel(m_installerContext)); + AddTask(new TaskUserDataManipulation(m_installerContext)); + if (m_installerContext.needEncryption) { + AddTask(new TaskEncryptResource(m_installerContext)); + } + + AddTask(new TaskManifestFile(m_installerContext)); + if (m_installerContext.widgetConfig.packagingType == + PKG_TYPE_HYBRID_WEB_APP) + { + AddTask(new TaskInstallOspsvc(m_installerContext)); + } + + AddTask(new TaskDatabase(m_installerContext)); + AddTask(new TaskAceCheck(m_installerContext)); + //TODO: remove widgetHandle from this task and move before database task + // by now widget handle is needed in ace check + // Any error in acecheck while update will break widget + AddTask(new TaskSmack(m_installerContext)); + AddTask(new TaskRemoveBackupFiles(m_installerContext)); + AddTask(new TaskPkgInfoUpdate(m_installerContext)); +} + +void JobWidgetInstall::SendProgress() +{ + using namespace PackageManager; + if (GetProgressFlag() != false) { + if (GetInstallerStruct().progressCallback != NULL) { + // send progress signal of pkgmgr + GetInstallerStruct().pkgmgrInterface->sendProgress(GetProgressPercent()); + + _D("Call widget install progressCallback"); + GetInstallerStruct().progressCallback( + GetInstallerStruct().userParam, + GetProgressPercent(), + GetProgressDescription()); + } + } +} + +void JobWidgetInstall::SendProgressIconPath(const std::string &path) +{ + using namespace PackageManager; + if (GetProgressFlag() != false) { + if (GetInstallerStruct().progressCallback != NULL) { + // send progress signal of pkgmgr + GetInstallerStruct().pkgmgrInterface->sendIconPath(path); + } + } +} + +void JobWidgetInstall::SendFinishedSuccess() +{ + using namespace PackageManager; + // TODO : sync should move to separate task. + sync(); + + if (INSTALL_LOCATION_TYPE_PREFER_EXTERNAL == m_installerContext.locationType) { + if (m_installerContext.isUpdateMode) { + WidgetInstallToExtSingleton::Instance().postUpgrade(true); + } else { + WidgetInstallToExtSingleton::Instance().postInstallation(true); + } + WidgetInstallToExtSingleton::Instance().deinitialize(); + } + + // remove widget install information file + unlink(m_installerContext.installInfo.c_str()); + + //inform widget info + JobWidgetInstall::displayWidgetInfo(); + + TizenAppId& tizenId = m_installerContext.widgetConfig.tzAppid; + + // send signal of pkgmgr + GetInstallerStruct().pkgmgrInterface->endJob(m_exceptionCaught); + + _D("Call widget install successfinishedCallback"); + GetInstallerStruct().finishedCallback(GetInstallerStruct().userParam, + DPL::ToUTF8String( + tizenId), Jobs::Exceptions::Success); +} + +void JobWidgetInstall::SendFinishedFailure() +{ + using namespace PackageManager; + // remove widget install information file + unlink(m_installerContext.installInfo.c_str()); + + // print error message + LOGE(COLOR_ERROR "Error number: %d" COLOR_END, m_exceptionCaught); + LOGE(COLOR_ERROR "Message: %s" COLOR_END, m_exceptionMessage.c_str()); + fprintf(stderr, "[Err:%d] %s", m_exceptionCaught, m_exceptionMessage.c_str()); + + TizenAppId & tizenId = m_installerContext.widgetConfig.tzAppid; + + _D("Call widget install failure finishedCallback"); + + // send signal of pkgmgr + GetInstallerStruct().pkgmgrInterface->endJob(m_exceptionCaught); + + GetInstallerStruct().finishedCallback(GetInstallerStruct().userParam, + DPL::ToUTF8String( + tizenId), m_exceptionCaught); +} + +void JobWidgetInstall::SaveExceptionData(const Jobs::JobExceptionBase &e) +{ + m_exceptionCaught = static_cast(e.getParam()); + m_exceptionMessage = e.GetMessage(); +} +void JobWidgetInstall::displayWidgetInfo() +{ + if (m_installerContext.widgetConfig.webAppType.appType == WrtDB::APP_TYPE_TIZENWEBAPP) + { + WidgetDAOReadOnly dao(m_installerContext.widgetConfig.tzAppid); + + std::ostringstream out; + WidgetLocalizedInfo localizedInfo = + W3CFileLocalization::getLocalizedInfo(dao.getTzAppId()); + + out << std::endl << + "===================================== INSTALLED WIDGET INFO =========" \ + "============================"; + out << std::endl << "Name: " << localizedInfo.name; + out << std::endl << "AppId: " << dao.getTzAppId(); + WidgetSize size = dao.getPreferredSize(); + out << std::endl << "Width: " << size.width; + out << std::endl << "Height: " << size.height; + out << std::endl << "Start File: " << + W3CFileLocalization::getStartFile(dao.getTzAppId()); + out << std::endl << "Version: " << dao.getVersion(); + out << std::endl << "Licence: " << + localizedInfo.license; + out << std::endl << "Licence Href: " << + localizedInfo.licenseHref; + out << std::endl << "Description: " << + localizedInfo.description; + out << std::endl << "Widget Id: " << dao.getGUID(); + + OptionalWidgetIcon icon = W3CFileLocalization::getIcon(dao.getTzAppId()); + DPL::OptionalString iconSrc = + !!icon ? icon->src : DPL::OptionalString::Null; + out << std::endl << "Icon: " << iconSrc; + + out << std::endl << "Preferences:"; + { + PropertyDAOReadOnly::WidgetPreferenceList list = dao.getPropertyList(); + FOREACH(it, list) + { + out << std::endl << " Key: " << + it->key_name; + out << std::endl << " Readonly: " << + it->readonly; + } + } + + out << std::endl; + + _D("%s", out.str().c_str()); + } +} +} //namespace WidgetInstall +} //namespace Jobs diff --git a/src_wearable/jobs/widget_install/job_widget_install.h b/src_wearable/jobs/widget_install/job_widget_install.h new file mode 100644 index 0000000..857863c --- /dev/null +++ b/src_wearable/jobs/widget_install/job_widget_install.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file job_widget_install.h + * @author Radoslaw Wicik r.wicik@samsung.com + * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com) + * @version 1.0 + * @brief Implementation file for main installer task + */ +#ifndef WRT_SRC_INSTALLER_CORE_JOB_JOB_WIDGET_INSTALL_H_ +#define WRT_SRC_INSTALLER_CORE_JOB_JOB_WIDGET_INSTALL_H_ + +#include +#include +#include +#include "widget_installer_struct.h" +#include + +using namespace Jobs::Exceptions; + +namespace Jobs { +namespace WidgetInstall { + +typedef JobProgressBase InstallerBase; +typedef JobContextBase WidgetInstallationBase; + +class JobWidgetInstall : + public Job, + public InstallerBase, + public WidgetInstallationBase + +{ + private: + InstallerContext m_installerContext; + + Jobs::Exceptions::Type m_exceptionCaught; + std::string m_exceptionMessage; + + public: + /** + * @brief Automaticaly sets installation process + */ + JobWidgetInstall(std::string const & widgetPath, + std::string const &tzPkgId, + const Jobs::WidgetInstall::WidgetInstallationStruct &installerStruct); + + //overrides + void SendProgress(); + void SendFinishedSuccess(); + void SendFinishedFailure(); + void SendProgressIconPath(const std::string &path); + + void SaveExceptionData(const Jobs::JobExceptionBase&); + void displayWidgetInfo(); + + //execution paths + void appendNewInstallationTaskList(); + void appendUpdateInstallationTaskList(); + void appendRDSUpdateTaskList(); + void appendRecoveryTaskList(); + void appendFotaInstallationTaskList(); + void appendFotaUpdateTaskList(); +}; +} //namespace WidgetInstall +} //namespace Jobs + +#endif // WRT_SRC_INSTALLER_CORE_JOB_JOB_WIDGET_INSTALL_H_ diff --git a/src_wearable/jobs/widget_install/languages.def b/src_wearable/jobs/widget_install/languages.def new file mode 100644 index 0000000..e9439b6 --- /dev/null +++ b/src_wearable/jobs/widget_install/languages.def @@ -0,0 +1,15 @@ +ADD(de, de-de) +ADD(el, el-gr) +ADD(en, en-us) +ADD(es, es-es) +ADD(fr, fr-fr) +ADD(it, it-it) +ADD(ja, ja-jp) +ADD(ko, ko-kr) +ADD(nl, nl-nl) +ADD(pt, pt-pt) +ADD(ru, ru-ru) +ADD(tr, tr-tr) +ADD(zh, zh-cn) +ADD(zh, zh-hk) +ADD(zh, zh-tw) diff --git a/src_wearable/jobs/widget_install/manifest.cpp b/src_wearable/jobs/widget_install/manifest.cpp new file mode 100755 index 0000000..0d509ac --- /dev/null +++ b/src_wearable/jobs/widget_install/manifest.cpp @@ -0,0 +1,575 @@ +/* + * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file manifest.cpp + * @author Mariusz Domanski (m.domanski@samsung.com) + */ + +#include "manifest.h" +#include "libxml_utils.h" +#include +#include +#include + +namespace Jobs { +namespace WidgetInstall { +void writeElement(xmlTextWriterPtr writer, const char * name, DPL::String body) +{ + int state = xmlTextWriterWriteElement(writer, BAD_CAST name, + BAD_CAST DPL::ToUTF8String( + body).c_str()); + if (state < 0) { + ThrowMsg(LibxmlUtils::Libxml2Error, "xmlTextWriterWriteElement failed"); + } +} + +void writeText(xmlTextWriterPtr writer, DPL::String text) +{ + int state = xmlTextWriterWriteString(writer, + BAD_CAST DPL::ToUTF8String(text).c_str()); + if (state < 0) { + ThrowMsg(LibxmlUtils::Libxml2Error, "xmlTextWriterWriteText failed"); + } +} + +void writeElement(xmlTextWriterPtr writer, const char * name, const char * body) +{ + int state = xmlTextWriterWriteElement(writer, BAD_CAST name, BAD_CAST body); + if (state < 0) { + ThrowMsg(LibxmlUtils::Libxml2Error, "xmlTextWriterWriteElement failed"); + } +} + +void writeElementWithOneAttribute(xmlTextWriterPtr writer, + const char * name, + DPL::String body, + const char * nameAttr, + DPL::String bodyAttr, + bool condition = true) +{ + startElement(writer, name); + writeAttribute(writer, nameAttr, bodyAttr, condition); + writeText(writer, body); + endElement(writer); +} + +void startElement(xmlTextWriterPtr writer, const char * name) +{ + int state = xmlTextWriterStartElement(writer, BAD_CAST name); + if (state < 0) { + ThrowMsg(LibxmlUtils::Libxml2Error, "xmlTextWriterStartElement failed"); + } +} + +void endElement(xmlTextWriterPtr writer) +{ + int state = xmlTextWriterEndElement(writer); + if (state < 0) { + ThrowMsg(LibxmlUtils::Libxml2Error, "xmlTextWriterEndElement failed"); + } +} + +void writeAttribute(xmlTextWriterPtr writer, + const char * name, + DPL::String body, + bool condition = true) +{ + if (!condition) { + return; + } + int state = xmlTextWriterWriteAttribute(writer, BAD_CAST name, + BAD_CAST DPL::ToUTF8String( + body).c_str()); + if (state < 0) { + ThrowMsg(LibxmlUtils::Libxml2Error, + "xmlTextWriterWriteAttribute failed"); + } +} + +void writeAttribute(xmlTextWriterPtr writer, + const char * name, + const char * body, + bool condition = true) +{ + if (!condition) { + return; + } + int state = xmlTextWriterWriteAttribute(writer, + BAD_CAST name, + BAD_CAST body); + if (state < 0) { + ThrowMsg(LibxmlUtils::Libxml2Error, + "xmlTextWriterWriteAttribute failed"); + } +} + +void Manifest::generate(DPL::String filename) +{ + xmlTextWriterPtr writer; + int state; + + //compression set to 0 + writer = xmlNewTextWriterFilename(DPL::ToUTF8String(filename).c_str(), 0); + + if (writer == NULL) { + ThrowMsg(LibxmlUtils::Libxml2Error, "xmlNewTextWriterFilename failed"); + } + state = xmlTextWriterSetIndent(writer, 1); + if (state < 0) { + ThrowMsg(LibxmlUtils::Libxml2Error, "xmlTextWriterSetIndent failed"); + } + + state = xmlTextWriterStartDocument(writer, NULL, "utf-8", NULL); + if (state < 0) { + ThrowMsg(LibxmlUtils::Libxml2Error, "xmlTextWriterStartDocument failed"); + } + this->serialize(writer); + state = xmlTextWriterEndDocument(writer); + if (state < 0) { + ThrowMsg(LibxmlUtils::Libxml2Error, "xmlTextWriterEndDocument failed"); + } + if (writer != NULL) { + xmlFreeTextWriter(writer); + writer = NULL; + } +} + +void Manifest::serialize(xmlTextWriterPtr writer) +{ + startElement(writer, "manifest"); + { + writeAttribute(writer, "xmlns", "http://tizen.org/ns/packages"); + writeAttribute(writer, "package", this->package); + writeAttribute(writer, "type", this->type); + writeAttribute(writer, "version", this->version); + if (!!this->installLocation) { + writeAttribute(writer, "install-location", (*this->installLocation)); + } + writeAttribute(writer, "storeclient-id", this->storeClientId, + !this->storeClientId.empty()); + writeAttribute(writer, "csc_path", this->cscPath, + !this->cscPath.empty()); + + FOREACH(l, this->label) + { + writeElementWithOneAttribute(writer, "label", l->getString(), + "xml:lang", l->getLang(), l->hasLang()); + } + FOREACH(i, this->icon) + { + writeElementWithOneAttribute(writer, "icon", i->getString(), + "xml:lang", i->getLang(), i->hasLang()); + } + FOREACH(a, this->author) + { + a->serialize(writer); + } + FOREACH(d, this->description) + { + writeElementWithOneAttribute(writer, "description", d->getString(), + "xml:lang", d->getLang(), d->hasLang()); + } + //FOREACH(c, this->compatibility) { c->serialize(writer); } + //FOREACH(d, this->deviceProfile) { d->serialize(writer); } +#ifdef SERVICE_ENABLED + FOREACH(s, this->serviceApplication) { + s->serialize(writer); + } +#endif + FOREACH(u, this->uiApplication) { + u->serialize(writer); + } +#ifdef IME_ENABLED + FOREACH(i, this->imeApplication) { + i->serialize(writer); + } +#endif + //FOREACH(f, this->font) { f->serialize(writer); } +#ifdef DBOX_ENABLED + FOREACH(l, this->livebox) { + l->serialize(writer); + } +#endif + FOREACH(acc, this->account) + { + acc->serialize(writer); + } + + if (!this->privileges.isEmpty()) { + this->privileges.serialize(writer); + } + } + endElement(writer); +} + +void Author::serialize(xmlTextWriterPtr writer) +{ + startElement(writer, "author"); + writeAttribute(writer, "email", this->email, !this->email.empty()); + writeAttribute(writer, "href", this->href, !this->href.empty()); + writeAttribute(writer, "xml:lang", this->lang, !this->lang.empty()); + writeText(writer, body); + endElement(writer); +} + +void UiApplication::serialize(xmlTextWriterPtr writer) +{ + startElement(writer, "ui-application"); + writeAttribute(writer, "appid", this->appid); + writeAttribute(writer, "exec", this->exec); + if (!!this->multiple) { + writeAttribute(writer, "multiple", (*this->multiple) ? "true" : "false"); + } + if (!!this->nodisplay) { + writeAttribute(writer, + "nodisplay", + (*this->nodisplay) ? "true" : "false"); + } + if (!!this->taskmanage) { + writeAttribute(writer, + "taskmanage", + (*this->taskmanage) ? "true" : "false"); + } + writeAttribute(writer, "type", this->type); + writeAttribute(writer, "extraid", this->extraid); + if (!!this->categories) { + writeAttribute(writer, "categories", (*this->categories)); + } + FOREACH(l, this->label) + { + writeElementWithOneAttribute(writer, "label", + l->getString(), "xml:lang", + l->getLang(), l->hasLang()); + } + FOREACH(i, this->icon) + { + startElement(writer, "icon"); + { + writeAttribute(writer, "xml:lang", i->getLang(), i->hasLang()); + writeAttribute(writer, "section", "small", i->isSmall()); + writeText(writer, i->getString()); + } + endElement(writer); + } + FOREACH(a, this->appControl) + { + a->serialize(writer); + } + FOREACH(c, this->appCategory) + { + startElement(writer, "category"); + writeAttribute(writer, "name", *c); + endElement(writer); + } + FOREACH(m, this->metadata) { + m->serialize(writer); + } + endElement(writer); +} + +#ifdef IME_ENABLED +void ImeApplication::serialize(xmlTextWriterPtr writer) +{ + startElement(writer, "ime"); + writeAttribute(writer, "appid", this->appid); + { + startElement(writer, "uuid"); + writeText(writer, this->uuid); + endElement(writer); + FOREACH(l, this->label) + { + writeElementWithOneAttribute(writer, "label", l->getString(), "xml:lang", l->getLang(), l->hasLang()); + } + startElement(writer, "languages"); + { + FOREACH(g, this->language) + { + startElement(writer, "language"); + writeText(writer, *g); + endElement(writer); + } + } + endElement(writer); + startElement(writer, "type"); + writeText(writer, this->iseType); + endElement(writer); + startElement(writer, "options"); + { + FOREACH(o, this->option) + { + startElement(writer, "option"); + writeText(writer, *o); + endElement(writer); + } + } + endElement(writer); + } + endElement(writer); +} +#endif + +#ifdef SERVICE_ENABLED +void ServiceApplication::serialize(xmlTextWriterPtr writer) +{ + startElement(writer, "ui-application"); + writeAttribute(writer, "component-type", this->component); + writeAttribute(writer, "auto-restart", (!!this->autoRestart && (*this->autoRestart)) ? "true" : "false"); + writeAttribute(writer, "on-boot", (!!this->onBoot && (*this->onBoot)) ? "true" : "false"); + writeAttribute(writer, "appid", this->appid); + writeAttribute(writer, "exec", this->exec); + writeAttribute(writer, "extraid", this->extraid); + if (!!this->nodisplay) { + writeAttribute(writer, "nodisplay", (*this->nodisplay) ? "true" : "false"); + } + if (!!this->multiple) { + writeAttribute(writer, "multiple", (*this->multiple) ? "true" : "false"); + } + writeAttribute(writer, "type", this->type); + if (!!this->taskmanage) { + writeAttribute(writer, "taskmanage", (*this->taskmanage) ? "true" : "false"); + } + if (!!this->categories) { + writeAttribute(writer, "categories", (*this->categories)); + } + FOREACH(l, this->label) + { + writeElementWithOneAttribute(writer, "label", + l->getString(), "xml:lang", + l->getLang(), l->hasLang()); + } + FOREACH(i, this->icon) + { + writeElementWithOneAttribute(writer, "icon", i->getString(), "xml:lang", + i->getLang(), i->hasLang()); + } + FOREACH(a, this->appControl) + { + a->serialize(writer); + } + FOREACH(c, this->appCategory) + { + startElement(writer, "category"); + writeAttribute(writer, "name", *c); + endElement(writer); +} + FOREACH(m, this->metadata) { + m->serialize(writer); + } + endElement(writer); +} +#endif + +void AppControl::serialize(xmlTextWriterPtr writer) +{ + startElement(writer, "app-control"); + FOREACH(o, this->operation) + { + startElement(writer, "operation"); + writeAttribute(writer, "name", *o); + endElement(writer); + } + FOREACH(u, this->uri) + { + startElement(writer, "uri"); + writeAttribute(writer, "name", *u); + endElement(writer); + } + FOREACH(m, this->mime) + { + startElement(writer, "mime"); + writeAttribute(writer, "name", *m); + endElement(writer); + } + endElement(writer); +} + +#ifdef DBOX_ENABLED +void LiveBox::serialize(xmlTextWriterPtr writer) +{ + startElement(writer, "livebox"); + if (!this->liveboxId.empty()) { + writeAttribute(writer, "appid", this->liveboxId); + } + + if (!this->primary.empty()) { + writeAttribute(writer, "primary", this->primary); + } + + if (!this->updatePeriod.empty()) { + writeAttribute(writer, "period", this->updatePeriod); + } + + writeAttribute(writer, "abi", "html"); + writeAttribute(writer, "network", "true"); + writeAttribute(writer, "nodisplay", "false"); + + if (!this->label.empty()) { + int defaultLabelChk = 0; + FOREACH(m, this->label) + { + std::pair boxLabel = *m; + startElement(writer, "label"); + if (!boxLabel.first.empty()) { + writeAttribute(writer, "xml:lang", boxLabel.first); + } else { + defaultLabelChk++; + } + writeText(writer, boxLabel.second); + endElement(writer); + } + if(!defaultLabelChk) { + startElement(writer, "label"); + writeText(writer, DPL::FromUTF8String("NO NAME")); + endElement(writer); + } + } + if (!this->icon.empty()) { + startElement(writer, "icon"); + writeText(writer, this->icon); + endElement(writer); + } + + if (!this->autoLaunch.empty()) { + startElement(writer, "launch"); + writeText(writer, this->autoLaunch); + endElement(writer); + } + + if (!this->box.boxSrc.empty() && + !this->box.boxMouseEvent.empty() && + !this->box.boxSize.empty()) + { + startElement(writer, "box"); + writeAttribute(writer, "type", "buffer"); + writeAttribute(writer, "mouse_event", this->box.boxMouseEvent); + writeAttribute(writer, "touch_effect", this->box.boxTouchEffect); + + FOREACH(it, this->box.boxSize) + { + startElement(writer, "size"); + if (!(*it).m_preview.empty()) { + writeAttribute(writer, "preview", (*it).m_preview); + } + if (!(*it).m_useDecoration.empty()) { + writeAttribute(writer, "need_frame", (*it).m_useDecoration); + } else { + // default value of use-decoration is "true" + writeAttribute(writer, "need_frame", DPL::String(L"true")); + } + + writeText(writer, (*it).m_size); + endElement(writer); + } + + startElement(writer, "script"); + writeAttribute(writer, "src", this->box.boxSrc); + endElement(writer); + + endElement(writer); + + if (!this->box.pdSrc.empty() && + !this->box.pdWidth.empty() && + !this->box.pdHeight.empty()) + { + startElement(writer, "pd"); + writeAttribute(writer, "type", "buffer"); + + startElement(writer, "size"); + DPL::String pdSize = this->box.pdWidth + DPL::String(L"x") + + this->box.pdHeight; + writeText(writer, pdSize); + endElement(writer); + + startElement(writer, "script"); + writeAttribute(writer, "src", this->box.pdSrc); + endElement(writer); + + endElement(writer); + } + } + + endElement(writer); +} +#endif + +void Account::serialize(xmlTextWriterPtr writer) +{ + startElement(writer, "account"); + { + startElement(writer, "account-provider"); + writeAttribute(writer, "appid", this->provider.appid); + writeAttribute(writer, "multiple-accounts-support", + this->provider.multiAccount); + + FOREACH(i, this->provider.icon) + { + startElement(writer, "icon"); + writeAttribute(writer, "section", i->first); + writeText(writer, i->second); + endElement(writer); + } + + bool setDefaultLang = false; + FOREACH(n, this->provider.name) + { + if (!setDefaultLang && n->getLang() == L"en-gb") { + writeElement(writer, "label", n->getString()); + setDefaultLang = true; + } + writeElementWithOneAttribute(writer, "label", + n->getString(), "xml:lang", + n->getLang(), n->hasLang()); + } + if (!setDefaultLang) { + writeElement(writer, "label", this->provider.name.begin()->getString()); + } + + FOREACH(c, this->provider.capability) + { + startElement(writer, "capability"); + writeText(writer, *c); + endElement(writer); + } + endElement(writer); + } + endElement(writer); +} + +void Privilege::serialize(xmlTextWriterPtr writer) +{ + startElement(writer, "privileges"); + { + FOREACH(it, this->name) + { + startElement(writer, "privilege"); + writeText(writer, *it); + endElement(writer); + } + } + endElement(writer); +} + +void Metadata::serialize(xmlTextWriterPtr writer) +{ + startElement(writer, "metadata"); + writeAttribute(writer, "key", *this->key); + if (!!this->value) { + writeAttribute(writer, "value", *this->value); + } + endElement(writer); +} +} //namespace Jobs +} //namespace WidgetInstall diff --git a/src_wearable/jobs/widget_install/manifest.h b/src_wearable/jobs/widget_install/manifest.h new file mode 100755 index 0000000..7d132fc --- /dev/null +++ b/src_wearable/jobs/widget_install/manifest.h @@ -0,0 +1,688 @@ +/* + * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file manifest.h + * @author Mariusz Domanski (m.domanski@samsung.com) + */ + +#ifndef INSTALLER_JOBS_MANIFEST_H +#define INSTALLER_JOBS_MANIFEST_H + +#include + +#include +#include + +#include +#include +#include +#include + +namespace Jobs { +namespace WidgetInstall { +/** + * @brief string with optional language attribute + */ +class StringWithLang +{ + public: + StringWithLang() { } + StringWithLang(DPL::String s) : string(s) { } + StringWithLang(DPL::String s, DPL::String l) : string(s), lang(l) { } + DPL::String getString() + { + return this->string; + } + DPL::String getLang() + { + return this->lang; + } + bool hasLang() + { + return !this->lang.empty(); + } + int operator==(const StringWithLang &other) + { + return (DPL::ToUTF8String(other.string) == DPL::ToUTF8String(string)) && + (DPL::ToUTF8String(other.lang) == DPL::ToUTF8String(lang)); + } + + private: + DPL::String string; + DPL::String lang; +}; + +class IconType : public StringWithLang +{ + public: + IconType() { } + IconType(DPL::String s) : StringWithLang(s), small(false) { } + IconType(DPL::String s, DPL::String l) : StringWithLang(s, l), small(false) { } + IconType(DPL::String s, bool m) : StringWithLang(s), small(m) { } + IconType(DPL::String s, DPL::String l, bool m) : StringWithLang(s, l), small(m) { } + + bool isSmall() + { + return small; + } + + int operator==(const IconType &other) + { + return (StringWithLang::operator==(other) && (other.small == small)); + } + + private: + bool small; +}; + +typedef StringWithLang LabelType, DescriptionType; + +/** + * These types are basicaly strings but they should allow usage of different + * range of characters or words (details in XML spec.). + * For simplicity DPL::Strings are used, although this can lead to XML + * validation + * errors (related to usage of not allowed characters in given places). + */ +typedef DPL::String NcnameType, NmtokenType, AnySimpleType, LangType; +typedef DPL::String OperationType, MimeType, UriType, TypeType, PackageType; +typedef DPL::OptionalString InstallLocationType, CategoriesType; +typedef DPL::String AppCategoryType; +typedef DPL::OptionalString KeyType, ValueType; + +#ifdef IME_ENABLED +typedef DPL::String UuidType, LanguageType, IseTypeType, OptionType; +#endif + +#ifdef SERVICE_ENABLED +typedef DPL::String ComponentType; +#endif + +/** + * xmllib2 wrappers + */ +void writeElement(xmlTextWriterPtr writer, const char * name, DPL::String body); +void writeText(xmlTextWriterPtr writer, DPL::String text); +void writeElement(xmlTextWriterPtr writer, const char * name, const char * body); +void writeElementWithOneAttribute(xmlTextWriterPtr writer, + const char * name, + const char * body, + const char * nameAttr, + DPL::String bodyAttr, + bool condition = true); +void startElement(xmlTextWriterPtr writer, const char * name); +void endElement(xmlTextWriterPtr writer); +void writeAttribute(xmlTextWriterPtr writer, const char * name, + DPL::String body, bool condition); +void writeAttribute(xmlTextWriterPtr writer, const char * name, + const char * body, bool condition); + +/** + * @brief author element + */ +class Author +{ + public: + Author() {} + Author(AnySimpleType e, + NcnameType h, + LangType l, + DPL::String b) : + email(e), href(h), lang(l), body(b) {} + void serialize(xmlTextWriterPtr writer); + + private: + AnySimpleType email; + NcnameType href; + LangType lang; + DPL::String body; +}; + +typedef Author AuthorType; + +/** + * @brief application-service element + */ +class AppControl +{ + public: + AppControl() {} + void addOperation(const OperationType &x) + { + this->operation.push_back(x); + } + void addUri(const UriType &x) + { + this->uri.push_back(x); + } + void addMime(const MimeType &x) + { + this->mime.push_back(x); + } + void serialize(xmlTextWriterPtr writer); + + private: + std::list operation; //attr name AnySimpleType + std::list uri; //attr name AnySimpleType + std::list mime; //attr name AnySimpleType +}; + +typedef AppControl AppControlType; + +/** + * @brief account element + */ +typedef std::list> IconListType; +typedef std::list DisplayNameListType; +typedef std::list AccountCapabilityType; + +struct AccountProvider +{ + NcnameType appid; + NcnameType multiAccount; + IconListType icon; + DisplayNameListType name; + AccountCapabilityType capability; +}; + +typedef AccountProvider AccountProviderType; + +class Account +{ + public: + Account() {} + void addAccountProvider(const AccountProvider &x) + { + this->provider = x; + } + void serialize(xmlTextWriterPtr writer); + + private: + AccountProviderType provider; +}; + +class Privilege +{ + public: + Privilege() {} + void addPrivilegeName(const DPL::String &x) + { + this->name.push_back(x); + } + bool isEmpty() + { + return this->name.empty(); + } + + void serialize(xmlTextWriterPtr writer); + + private: + std::list name; +}; + +typedef Privilege PrivilegeType; + +class Metadata +{ + public: + Metadata(KeyType k, ValueType v) : + key(k), + value(v) + {} + void serialize(xmlTextWriterPtr writer); + + private: + KeyType key; + ValueType value; +}; + +typedef Metadata MetadataType; + +#ifdef IME_ENABLED +/** + * @brief ime-application element + */ +class ImeApplication +{ + public: + ImeApplication() {} + void setAppid(const NcnameType &x) + { + this->appid = x; + } + void addLabel(const LabelType &x) + { + this->label.push_back(x); + } + void addUuid(const UuidType &x) + { + this->uuid = x; + } + void addLanguage(const LanguageType &x) + { + this->language.push_back(x); + } + void addIseType(const IseTypeType &x) + { + this->iseType = x; + } + void addOption(const OptionType &x) + { + this->option.push_back(x); + } + void serialize(xmlTextWriterPtr writer); + + private: + NcnameType appid; + std::list label; + DPL::String uuid; + std::list language; + DPL::String iseType; + std::list option; +}; + +typedef ImeApplication ImeApplicationType; +#endif + +#ifdef SERVICE_ENABLED +/** + * @brief service-application element + */ + +class ServiceApplication +{ + public: + ServiceApplication() {} + void setAppid(const NcnameType &x) + { + this->appid = x; + } + void setComponent(const ComponentType &x) + { + this->component = x; + } + void setAutoRestart(bool x) + { + this->autoRestart = x; + } + void setOnBoot(bool x) + { + this->onBoot = x; + } + void setExec(const AnySimpleType &x) + { + this->exec = x; + } + void setExtraid(const NcnameType &x) + { + this->extraid = x; + } + void setNodisplay(bool x) + { + this->nodisplay = x; + } + void setMultiple(bool x) + { + this->multiple = x; + } + void setType(const TypeType &x) + { + this->type = x; + } + void setTaskmanage(bool x) + { + this->taskmanage = x; + } + void setCategories(const NcnameType &x) + { + this->categories = x; + } + void addLabel(const LabelType &x) + { + this->label.push_back(x); + } + void addIcon(const IconType &x) + { + this->icon.push_back(x); + } + void addAppControl(const AppControlType &x) + { + this->appControl.push_back(x); + } + void addAppCategory(const AppCategoryType &x) + { + this->appCategory.push_back(x); + } + void addMetadata(const MetadataType &m) + { + this->metadata.push_back(m); + } + void serialize(xmlTextWriterPtr writer); + + DPL::OptionalBool isNoDisplay() { + return this->nodisplay; + } + + private: + NcnameType appid; + DPL::String component; + DPL::OptionalBool autoRestart; + DPL::OptionalBool onBoot; + AnySimpleType exec; + NcnameType extraid; + DPL::OptionalBool nodisplay; + DPL::OptionalBool multiple; + TypeType type; + DPL::OptionalBool taskmanage; + CategoriesType categories; + std::list label; + std::list icon; + std::list appControl; + std::list appCategory; + std::list metadata; +}; + +typedef ServiceApplication ServiceApplicationType; + +#endif + +/** + * @brief ui-application element + */ +class UiApplication +{ + public: + UiApplication() {} + void setAppid(const NcnameType &x) + { + this->appid = x; + } + void setExtraid(const NcnameType &x) + { + this->extraid = x; + } + void setExec(const AnySimpleType &x) + { + this->exec = x; + } + void setMultiple(bool x) + { + this->multiple = x; + } + void setNodisplay(bool x) + { + this->nodisplay = x; + } + void setTaskmanage(bool x) + { + this->taskmanage = x; + } + void setType(const TypeType &x) + { + this->type = x; + } + void setCategories(const NcnameType &x) + { + this->categories = x; + } + void addLabel(const LabelType &x) + { + this->label.push_back(x); + } + void addIcon(const IconType &x) + { + this->icon.push_back(x); + } + void addAppControl(const AppControlType &x) + { + this->appControl.push_back(x); + } + void addAppCategory(const AppCategoryType &x) + { + this->appCategory.push_back(x); + } + void addMetadata(const MetadataType &m) + { + this->metadata.push_back(m); + } + void serialize(xmlTextWriterPtr writer); + + DPL::OptionalBool isNoDisplay() { + return this->nodisplay; + } + + private: + NcnameType appid; + NcnameType extraid; + AnySimpleType exec; + DPL::OptionalBool multiple; + DPL::OptionalBool nodisplay; + DPL::OptionalBool taskmanage; + TypeType type; + CategoriesType categories; + std::list label; + std::list icon; + std::list appControl; + std::list appCategory; + std::list metadata; +}; + +typedef UiApplication UiApplicationType; + +#ifdef DBOX_ENABLED +/** + * @brief LiveBox element + */ +typedef WrtDB::ConfigParserData::LiveboxInfo::BoxSizeList BoxSizeType; +typedef WrtDB::ConfigParserData::LiveboxInfo::BoxLabelList BoxLabelType; + +struct BoxInfo +{ + NcnameType boxSrc; + NcnameType boxMouseEvent; + NcnameType boxTouchEffect; + BoxSizeType boxSize; + NcnameType pdSrc; + NcnameType pdWidth; + NcnameType pdHeight; +}; +typedef BoxInfo BoxInfoType; + +class LiveBox +{ + public: + LiveBox() { } + void setLiveboxId(const NcnameType &x) + { + this->liveboxId = x; + } + void setPrimary(const NcnameType &x) + { + this->primary = x; + } + void setAutoLaunch(const NcnameType &x) + { + this->autoLaunch = x; + } + void setUpdatePeriod(const NcnameType &x) + { + this->updatePeriod = x; + } + void setLabel(const BoxLabelType &x) + { + this->label = x; + } + void setIcon(const NcnameType &x) + { + this->icon = x; + } + void setBox(const BoxInfoType &x) + { + this->box = x; + } + + void serialize(xmlTextWriterPtr writer); + + private: + NcnameType liveboxId; + NcnameType primary; + NcnameType autoLaunch; + NcnameType updatePeriod; + NcnameType timeout; + BoxLabelType label; + NcnameType icon; + NcnameType lang; + BoxInfoType box; +}; + +typedef LiveBox LiveBoxInfo; +#endif + +/** + * @brief manifest element + * + * Manifest xml file representation. + */ +class Manifest +{ + public: + Manifest() {} + void serialize(xmlTextWriterPtr writer); + void generate(DPL::String filename); + + void addLabel(const LabelType &x) + { +#ifdef MULTIPROCESS_SERVICE_SUPPORT + auto pos = std::find(label.begin(), label.end(), x); + if (pos == label.end()) { + this->label.push_back(x); + } +#else + this->label.push_back(x); +#endif + } + void addIcon(const IconType &x) + { + this->icon.push_back(x); + } + void addAuthor(const AuthorType &x) + { + this->author.push_back(x); + } + void addDescription(const DescriptionType &x) + { + this->description.push_back(x); + } + // void addCompatibility(const CompatibilityType &x) + // { + // this->compatibility.push_back(x); + // } + // void addDeviceProfile(const DeviceProfileType &x) + // { + // this->deviceProfile.push_back(x); + // } + void addUiApplication(const UiApplicationType &x) + { + this->uiApplication.push_back(x); + } +#ifdef IME_ENABLED + void addImeApplication(const ImeApplicationType &x) + { + this->imeApplication.push_back(x); + } +#endif +#ifdef SERVICE_ENABLED + void addServiceApplication(const ServiceApplicationType &x) + { + this->serviceApplication.push_back(x); + } +#endif + // void addFont(const FontType &x) { this->font.push_back(x); } + +#ifdef DBOX_ENABLED + void addLivebox(const LiveBoxInfo &x) + { + this->livebox.push_back(x); + } +#endif + + void addAccount(const Account &x) + { + this->account.push_back(x); + } + + void addPrivileges(const PrivilegeType &x) + { + this->privileges = x; + } + + void setInstallLocation(const InstallLocationType &x) + { + this->installLocation = x; + } + void setPackage(const NcnameType &x) + { + this->package = x; + } + void setType(const PackageType &x) + { + this->type = x; + } + void setVersion(const NmtokenType &x) + { + this->version = x; + } + void setStoreClientId(const NcnameType &x) + { + this->storeClientId= x; + } + void setCscPath(const NcnameType &x) + { + this->cscPath = x; + } + + private: + std::list label; + std::list icon; + std::list author; + std::list description; + // std::list compatibility; + // std::list deviceProfile; +#ifdef SERVICE_ENABLED + std::list serviceApplication; +#endif + std::list uiApplication; +#ifdef IME_ENABLED + std::list imeApplication; +#endif + // std::list font; +#ifdef DBOX_ENABLED + std::list livebox; +#endif + InstallLocationType installLocation; + NcnameType package; + PackageType type; + NmtokenType version; + std::list account; + PrivilegeType privileges; + NcnameType storeClientId; + NcnameType cscPath; + +}; +} //namespace Jobs +} //namespace WidgetInstall + +#endif //INSTALLER_JOBS_MANIFEST_H diff --git a/src_wearable/jobs/widget_install/task_ace_check.cpp b/src_wearable/jobs/widget_install/task_ace_check.cpp new file mode 100755 index 0000000..7285492 --- /dev/null +++ b/src_wearable/jobs/widget_install/task_ace_check.cpp @@ -0,0 +1,245 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file task_ace_check.cpp + * @author Pawel Sikorski (p.sikorski@samsung.com) + * @version 1.0 + * @brief Implementation file for installer task ace check + */ + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include + +namespace Jobs { +namespace WidgetInstall { +TaskAceCheck::TaskAceCheck(InstallerContext& context) : + DPL::TaskDecl(this), + m_context(context) +{ + AddStep(&TaskAceCheck::StartStep); + AddStep(&TaskAceCheck::StepPrepareForAce); + AddStep(&TaskAceCheck::StepAceCheck); + AddStep(&TaskAceCheck::StepProcessAceResponse); + AddStep(&TaskAceCheck::StepCheckAceResponse); + AddStep(&TaskAceCheck::EndStep); +} + +void TaskAceCheck::StepPrepareForAce() +{ + m_context.featureLogic = + FeatureLogicPtr(new FeatureLogic(m_context.widgetConfig.tzAppid)); + m_context.job->UpdateProgress( + InstallerContext::INSTALL_ACE_PREPARE, + "Widget Access Control Check Prepared"); +} + +void TaskAceCheck::StepAceCheck() +{ + WrtDB::WidgetDAO dao(m_context.widgetConfig.tzAppid); + _D("StepAceCheck!"); + // This widget does not use any device cap + if (m_context.featureLogic->isDone()) { + return; + } + + _D("StepAceCheck!"); + DPL::String deviceCap = m_context.featureLogic->getDevice(); + + _D("StepAceCheck!"); + _D("DevCap is : %ls", deviceCap.c_str()); + + std::string devCapStr = DPL::ToUTF8String(deviceCap); + ace_policy_result_t policyResult = ACE_DENY; + + if (m_context.mode.installTime == InstallMode::InstallTime::PRELOAD) { + _D("This widget is preloaded. So ace check will be skiped"); + policyResult = ACE_PERMIT; + } else { + ace_return_t ret = ace_get_policy_result( + const_cast(devCapStr.c_str()), + dao.getHandle(), + &policyResult); + if (ACE_OK != ret) { + ThrowMsg(Exceptions::AceCheckFailed, "Instalation failure. " + "ACE check failure"); + } + } + + _D("PolicyResult is : %d", static_cast(policyResult)); + m_context.staticPermittedDevCaps.insert(std::make_pair(deviceCap, + policyResult == + ACE_PERMIT)); + + m_context.featureLogic->setAceResponse(policyResult != ACE_DENY); +} + +void TaskAceCheck::StepProcessAceResponse() +{ + if (m_context.widgetConfig.packagingType == + WrtDB::PKG_TYPE_HOSTED_WEB_APP) + { + return; + } + + _D("StepProcessAceResponse"); + m_context.featureLogic->next(); + + // No device caps left to process + if (m_context.featureLogic->isDone()) { + WrtDB::WidgetDAO dao(m_context.widgetConfig.tzAppid); +#ifdef SERVICE_ENABLED + std::list serviceList; + FOREACH(it , m_context.widgetConfig.configInfo.serviceAppInfoList){ + WrtDB::WidgetDAO serviceDao(it->serviceId); + serviceList.push_back(serviceDao.getHandle()); + } +#endif + _D("All responses has been received from ACE."); + // Data to convert to C API + std::vector devCaps; + std::vector devCapsSmack; + // Saving static dev cap permissions + FOREACH(cap, m_context.staticPermittedDevCaps) { + _D("staticPermittedDevCaps : %ls smack: %d", cap->first.c_str(), cap->second); + std::string devCapStr = DPL::ToUTF8String(cap->first); + devCaps.push_back(devCapStr); + devCapsSmack.push_back(cap->second); + } + ace_requested_dev_cap_list_t list; + list.count = devCaps.size(); + list.items = new ace_requested_dev_cap_t[list.count]; + + for (unsigned int i = 0; i < devCaps.size(); ++i) { + list.items[i].device_capability = + const_cast(devCaps[i].c_str()); + list.items[i].smack_granted = + devCapsSmack[i] ? ACE_TRUE : ACE_FALSE; + } + //TODO: remove dao.getHandle() + int ret = ace_set_requested_dev_caps(dao.getHandle(), &list); +#ifdef SERVICE_ENABLED + FOREACH(it, serviceList){ + ret |= ace_set_requested_dev_caps(*it, &list); + } +#endif + delete[] list.items; + + if (ACE_OK != static_cast(ret)) { + ThrowMsg(Exceptions::AceCheckFailed, "Instalation failure. " + "ACE failure"); + } + + std::set acceptedFeature; + auto it = m_context.featureLogic->resultBegin(); + for (; it != m_context.featureLogic->resultEnd(); ++it) { + if (!(it->rejected)) { + acceptedFeature.insert(DPL::ToUTF8String(it->name)); + } + } + ace_feature_list_t featureList; + featureList.count = acceptedFeature.size(); + featureList.items = new ace_string_t[featureList.count]; + + size_t i = 0; + for (std::set::const_iterator iter = acceptedFeature.begin(); + iter != acceptedFeature.end(); ++iter) + { + _D("Accepted feature item: %s", iter->c_str()); + featureList.items[i] = const_cast(iter->c_str()); + i++; + } + + //TODO: remove dao.getHandle() + ret = ace_set_accepted_feature(dao.getHandle(), &featureList); +#ifdef SERVICE_ENABLED + FOREACH(it, serviceList){ + ret |= ace_set_accepted_feature(*it, &featureList); + } +#endif + delete[] featureList.items; + + if (ACE_OK != static_cast(ret)) { + _E("Error in ace_set_feature"); + ThrowMsg(Exceptions::AceCheckFailed, "Instalation failure. " + "ace_set_feature failure."); + } + return; + } + + _D("Next device cap."); + // Process next device cap + SwitchToStep(&TaskAceCheck::StepAceCheck); +} + +void TaskAceCheck::StepCheckAceResponse() +{ + _D("Checking ACE response"); + if (m_context.featureLogic->isRejected()) { + _E("Installation failure. Some devCap was not accepted by ACE."); + ThrowMsg( + Exceptions::PrivilegeLevelViolation, + "Instalation failure. " + "Some deviceCap was not accepted by ACE."); + } + _D("Updating \"feature reject status\" in database!"); + auto it = m_context.featureLogic->resultBegin(); + auto end = m_context.featureLogic->resultEnd(); + for (; it != end; ++it) { + _D(" |- Feature: %ls has reject status: %d", it->name.c_str(), it->rejected); + if (it->rejected) { + WrtDB::WidgetDAO dao(m_context.widgetConfig.tzAppid); + dao.updateFeatureRejectStatus(*it); + +#ifdef SERVICE_ENABLED + FOREACH( svcApp , m_context.widgetConfig.configInfo.serviceAppInfoList){ + WrtDB::WidgetDAO dao(svcApp->serviceId); + dao.updateFeatureRejectStatus(*it); + } +#endif + } + } + _D("Installation continues..."); +} + +void TaskAceCheck::StartStep() +{ + LOGD("--------- : START ----------"); +} + +void TaskAceCheck::EndStep() +{ + m_context.job->UpdateProgress( + InstallerContext::INSTALL_ACE_CHECK, + "Widget Access Control Check Finished"); + + LOGD("--------- : END ----------"); +} +} //namespace WidgetInstall +} //namespace Jobs diff --git a/src_wearable/jobs/widget_install/task_ace_check.h b/src_wearable/jobs/widget_install/task_ace_check.h new file mode 100644 index 0000000..e4ce90d --- /dev/null +++ b/src_wearable/jobs/widget_install/task_ace_check.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file task_ace_check.h + * @author Pawel Sikorski (p.sikorski@samsung.com) + * @version 1.0 + * @brief Header file for installer task ace check + */ +#ifndef INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_ACE_CHECK_H +#define INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_ACE_CHECK_H + +#include + +class InstallerContext; + +namespace Jobs { +namespace WidgetInstall { +class TaskAceCheck : + public DPL::TaskDecl +{ + private: + InstallerContext& m_context; + + void StepPrepareForAce(); + void StepAceCheck(); + void StepProcessAceResponse(); + void StepCheckAceResponse(); + + void StartStep(); + void EndStep(); + + public: + TaskAceCheck(InstallerContext& context); +}; +} //namespace WidgetInstall +} //namespace Jobs + +#endif /* INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_ACE_CHECK_H */ diff --git a/src_wearable/jobs/widget_install/task_certify.cpp b/src_wearable/jobs/widget_install/task_certify.cpp new file mode 100644 index 0000000..3e8925c --- /dev/null +++ b/src_wearable/jobs/widget_install/task_certify.cpp @@ -0,0 +1,403 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file task_certify.cpp + * @author Pawel Sikorski (p.sikorski@samgsung.com) + * @version + * @brief + */ + +//SYSTEM INCLUDES +#include +#include +#include +#include +#include +#include + +//WRT INCLUDES +#include +#include +#include +#include "wac_widget_id.h" + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +using namespace ValidationCore; +using namespace WrtDB; + +namespace { +const int SIGNATURE_FILE_NUMBER_DISTRIBUTOR1 = 1; +const int SIGNATURE_FILE_NUMBER_DISTRIBUTOR2 = 2; + +WidgetCertificateData toWidgetCertificateData(const SignatureData &data, + bool root) +{ + WidgetCertificateData result; + + result.chainId = data.getSignatureNumber(); + _D("result.chainId : %d", result.chainId); + + result.owner = data.isAuthorSignature() ? + WidgetCertificateData::AUTHOR : WidgetCertificateData::DISTRIBUTOR; + + if (data.isAuthorSignature()) { + result.owner = WidgetCertificateData::AUTHOR; + } else { + if (SIGNATURE_FILE_NUMBER_DISTRIBUTOR1 == data.getSignatureNumber()) { + result.owner = WidgetCertificateData::DISTRIBUTOR; + } else if (SIGNATURE_FILE_NUMBER_DISTRIBUTOR2 == + data.getSignatureNumber()){ + result.owner = WidgetCertificateData::DISTRIBUTOR2; + } else { + result.owner = WidgetCertificateData::UNKNOWN; + } + } + + result.type = root ? + WidgetCertificateData::ROOT : WidgetCertificateData::ENDENTITY; + + CertificatePtr certificate; + + if (root) { + certificate = data.getRootCaCertificatePtr(); + } else { + certificate = data.getEndEntityCertificatePtr(); + } + + AssertMsg(certificate && !!certificate->getCommonName(), + "CommonName is Null"); + + result.strCommonName = *certificate->getCommonName(); + + result.strMD5Fingerprint = std::string("md5 ") + + Certificate::FingerprintToColonHex( + certificate->getFingerprint(Certificate::FINGERPRINT_MD5)); + + result.strSHA1Fingerprint = std::string("sha-1 ") + + Certificate::FingerprintToColonHex( + certificate->getFingerprint(Certificate::FINGERPRINT_SHA1)); + + return result; +} + +CertificatePtr getOldAuthorSignerCertificate(DPL::String appid) +{ + CertificateChainList chainList; + WidgetDAOReadOnly dao(appid); + chainList = dao.getWidgetCertificate(SIGNATURE_AUTHOR); + FOREACH(it, chainList) + { + ValidationCore::CertificateCollection chain; + if (false == chain.load(*it)) { + _E("Chain is broken"); + } + + if (!chain.sort()) { + _E("Chain failed at sorting"); + } + + ValidationCore::CertificateList list = chain.getCertificateList(); + + FOREACH(cert, list) + { + if (!(*cert)->isRootCert() && !(*cert)->isCA()) { + return *cert; + } + } + } + return CertificatePtr(); +} +} // namespace anonymous + +namespace Jobs { +namespace WidgetInstall { +TaskCertify::TaskCertify(InstallerContext &inCont) : + DPL::TaskDecl(this), + m_contextData(inCont) +{ + AddStep(&TaskCertify::StartStep); + AddStep(&TaskCertify::stepSignature); + // certi comparison determines whether the update. + if (true == m_contextData.isUpdateMode) { + AddStep(&TaskCertify::stepVerifyUpdate); + } + AddStep(&TaskCertify::EndStep); +} + +void TaskCertify::processDistributorSignature(const SignatureData &data) +{ + // this signature is verified - + // no point in check domain WAC_ROOT and WAC_RECOGNIZED + m_contextData.widgetSecurity.setDistributorSigned(true); + + CertificateCollection collection; + collection.load(data.getCertList()); + AssertMsg(collection.sort(), + "Certificate collection can't sort"); + + AssertMsg(collection.isChain(), + "Certificate collection is not able to create chain. " + "It is not possible to verify this signature."); + + if (SIGNATURE_FILE_NUMBER_DISTRIBUTOR1 == data.getSignatureNumber()) { + m_contextData.widgetSecurity.getCertificateChainListRef().push_back( + collection); + } else { + m_contextData.widgetSecurity.getCertificateChainList2Ref().push_back( + collection); + } + + m_contextData.widgetSecurity.getCertificateListRef().push_back( + toWidgetCertificateData(data, true)); + m_contextData.widgetSecurity.getCertificateListRef().push_back( + toWidgetCertificateData(data, false)); +} + +void TaskCertify::processAuthorSignature(const SignatureData &data) +{ + using namespace ValidationCore; + _D("DNS Identity match!"); + // this signature is verified or widget is distributor signed + m_contextData.widgetSecurity.setAuthorCertificatePtr(data.getEndEntityCertificatePtr()); + CertificatePtr test = m_contextData.widgetSecurity.getAuthorCertificatePtr(); + + m_contextData.widgetSecurity.getCertificateListRef().push_back( + toWidgetCertificateData(data, true)); + m_contextData.widgetSecurity.getCertificateListRef().push_back( + toWidgetCertificateData(data, false)); + + // match widget_id with one from dns identity set + WacWidgetId widgetId(m_contextData.widgetConfig.configInfo.widget_id); + + CertificatePtr cert = data.getEndEntityCertificatePtr(); + Assert(cert); + Certificate::AltNameSet dnsIdentity = cert->getAlternativeNameDNS(); + + CertificateCollection collection; + collection.load(data.getCertList()); + collection.sort(); + AssertMsg(collection.isChain(), + "Certificate collection is not able to create chain. " + "It is not possible to verify this signature."); + + m_contextData.widgetSecurity.getAuthorsCertificateChainListRef().push_back( + collection); + + FOREACH(it, dnsIdentity){ + if (widgetId.matchHost(*it)) { + m_contextData.widgetSecurity.setRecognized(true); + return; + } + } +} + +void TaskCertify::getSignatureFiles(std::string path, SignatureFileInfoSet& file) +{ + _D("path : %s", path.c_str()); + SignatureFileInfoSet signatureFiles; + SignatureFinder signatureFinder(path); + if (SignatureFinder::NO_ERROR != signatureFinder.find(file)) { + _E("Error in Signature Finder : %s", path.c_str()); + ThrowMsg(Exceptions::SignatureNotFound, + "Error openig temporary widget directory"); + } +} + +void TaskCertify::stepSignature() +{ + LOGD("================ Step: <> ENTER ==============="); + + std::string widgetPath; + widgetPath = m_contextData.locations->getPackageInstallationDir() + "/"; + + SignatureFileInfoSet signatureFiles; + + Try { + getSignatureFiles(widgetPath, signatureFiles); + + if (signatureFiles.size() <= 0) { + widgetPath += std::string(WrtDB::GlobalConfig::GetWidgetSrcPath()) + + "/"; + if (0 == access(widgetPath.c_str(), F_OK)) { + getSignatureFiles(widgetPath, signatureFiles); + } + } + } Catch(Exceptions::SignatureNotFound) { + ReThrowMsg(Exceptions::SignatureNotFound, widgetPath); + } + + SignatureFileInfoSet::reverse_iterator iter = signatureFiles.rbegin(); + _D("Number of signatures: %d", signatureFiles.size()); + + for (; iter != signatureFiles.rend(); ++iter) { + _D("Checking signature with id=%d", iter->getFileNumber()); + SignatureData data(widgetPath + iter->getFileName(), + iter->getFileNumber()); + + Try { + SignatureReader xml; + xml.initialize(data, GlobalConfig::GetSignatureXmlSchema()); + xml.read(data); + + WrtSignatureValidator::Result result; + + WrtSignatureValidator validator( + WrtSignatureValidator::TIZEN, + !GlobalSettings:: + OCSPTestModeEnabled(), + !GlobalSettings:: + CrlTestModeEnabled(), + false); + + result = validator.check(data, widgetPath); + + if (m_contextData.mode.installTime == InstallMode::InstallTime::PRELOAD + || m_contextData.mode.command == InstallMode::Command::RECOVERY + || m_contextData.mode.installTime == InstallMode::InstallTime::FOTA) + { + result = WrtSignatureValidator::SIGNATURE_VERIFIED; + } + + if (result == WrtSignatureValidator::SIGNATURE_REVOKED) { + _W("Certificate is REVOKED"); + ThrowMsg(Exceptions::CertificateExpired, + "Certificate is REVOKED"); + } + + if (result == WrtSignatureValidator::SIGNATURE_INVALID && + iter->getFileNumber() <= 1) { + _W("Signature is INVALID"); + // TODO change exception name + ThrowMsg(Exceptions::SignatureInvalid, + "Invalid Package"); + } + + if (data.isAuthorSignature()) { + if (result == WrtSignatureValidator::SIGNATURE_VERIFIED ) { + processAuthorSignature(data); + } + } else { + if (result != WrtSignatureValidator::SIGNATURE_INVALID) { + processDistributorSignature(data); + } + } + } Catch(ParserSchemaException::Base) { + _E("Error occured in ParserSchema."); + ReThrowMsg(Exceptions::SignatureInvalid, + "Error occured in ParserSchema."); + } + } + + if (signatureFiles.empty()) { + _D("No signature files has been found."); + } + + LOGD("================ Step: <> DONE ================"); + + m_contextData.job->UpdateProgress( + InstallerContext::INSTALL_DIGSIG_CHECK, + "Widget Signature checked"); +} + +bool TaskCertify::isTizenWebApp() const +{ + bool ret = FALSE; + if (m_contextData.widgetConfig.webAppType.appType == WrtDB::AppType::APP_TYPE_TIZENWEBAPP) + { + ret = TRUE; + } + + return ret; +} + +void TaskCertify::stepVerifyUpdate() +{ + LOGD("================ Step: <> ENTER ==============="); + + std::string oldAuthorCert; + + int ret = 0; + pkgmgrinfo_certinfo_h handle; + const char *authorCert = NULL; + ret = pkgmgrinfo_pkginfo_create_certinfo(&handle); + if (PMINFO_R_OK == ret) { + ret = pkgmgrinfo_pkginfo_load_certinfo(DPL::ToUTF8String( + m_contextData.widgetConfig.tzPkgid).c_str(), handle); + if (PMINFO_R_OK == ret) { + ret = pkgmgrinfo_pkginfo_get_cert_value(handle, + PMINFO_AUTHOR_SIGNER_CERT, &authorCert); + if (PMINFO_R_OK == ret) { + oldAuthorCert = (NULL != authorCert)? authorCert : ""; + } + } + pkgmgrinfo_pkginfo_destroy_certinfo(handle); + } + + if (oldAuthorCert.empty()) { + _D("Old cert is empty."); + } else { + ValidationCore::CertificatePtr certPtr = m_contextData.widgetSecurity.getAuthorCertificatePtr(); + if (certPtr == NULL) { + ThrowMsg(Exceptions::NotMatchedCertification, "No author certificates"); + } + + DPL::String newAuthorPublicKeyStr = certPtr->getPublicKeyString(); + //compare with public key + ValidationCore::Certificate installedCert(oldAuthorCert , ValidationCore::Certificate::FORM_BASE64); + DPL::String installedPublicKeyStr = installedCert.getPublicKeyString(); + if (0 != installedPublicKeyStr.compare(newAuthorPublicKeyStr)) { + _D("old widget's author public key : %ls", + installedPublicKeyStr.c_str()); + _D("new widget's author public key: %ls", + newAuthorPublicKeyStr.c_str()); + ThrowMsg(Exceptions::NotMatchedCertification, + "Author signer certificates doesn't match \ + between old widget and installing widget"); + } + + } + LOGD("================ Step: <> DONE ==============="); +} + +void TaskCertify::StartStep() +{ + LOGD("--------- : START ----------"); +} + +void TaskCertify::EndStep() +{ + LOGD("Step: <>"); + + m_contextData.job->UpdateProgress( + InstallerContext::INSTALL_CERT_CHECK, + "Widget Certification Check Finished"); + + LOGD("--------- : END ----------"); +} +} //namespace WidgetInstall +} //namespace Jobs + diff --git a/src_wearable/jobs/widget_install/task_certify.h b/src_wearable/jobs/widget_install/task_certify.h new file mode 100644 index 0000000..6a59781 --- /dev/null +++ b/src_wearable/jobs/widget_install/task_certify.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file task_certify.h + * @author Pawel Sikorski (p.sikorski@samgsung.com) + * @version + * @brief + */ +#ifndef INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_CERTIFY_H +#define INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_CERTIFY_H + +//SYSTEM INCLUDES +#include +#include +#include + +//WRT INCLUDES +#include + +class InstallerContext; + +namespace ValidationCore { +class SignatureData; +} + +namespace Jobs { +namespace WidgetInstall { +class TaskCertify : + public DPL::TaskDecl +{ + public: + TaskCertify(InstallerContext &inCont); + + private: + //data + InstallerContext& m_contextData; + + //steps + void stepSignature(); + void stepVerifyUpdate(); + + void StartStep(); + void EndStep(); + + void processDistributorSignature(const ValidationCore::SignatureData &data); + void processAuthorSignature(const ValidationCore::SignatureData &data); + void getSignatureFiles(std::string path, + ValidationCore::SignatureFileInfoSet& file); + + bool isTizenWebApp() const; +}; +} //namespace WidgetInstall +} //namespace Jobs + +#endif // INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_CERTIFY_H diff --git a/src_wearable/jobs/widget_install/task_certify_level.cpp b/src_wearable/jobs/widget_install/task_certify_level.cpp new file mode 100755 index 0000000..1b9bffe --- /dev/null +++ b/src_wearable/jobs/widget_install/task_certify_level.cpp @@ -0,0 +1,280 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file task_certify_level.cpp + * @author Jihoon Chung (jihoon.chung@samgsung.com) + * @version + * @brief + */ + +//SYSTEM INCLUDES +#include +#include +#include + +//WRT INCLUDES +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +using namespace ValidationCore; +using namespace WrtDB; + +namespace Jobs { +namespace WidgetInstall { +TaskCertifyLevel::TaskCertifyLevel(InstallerContext &inCont) : + DPL::TaskDecl(this), + m_contextData(inCont) +{ + AddStep(&TaskCertifyLevel::StartStep); + AddStep(&TaskCertifyLevel::stepCertifyLevel); + AddStep(&TaskCertifyLevel::EndStep); +} + +void TaskCertifyLevel::stepCertifyLevel() +{ + LOGD("================ Step: <> ENTER ==============="); + if (!checkConfigurationLevel(getCertifyLevel())) { + ThrowMsg(Exceptions::PrivilegeLevelViolation, "setting level violate"); + } + LOGD("================ Step: <> DONE ================"); +} + +void TaskCertifyLevel::getSignatureFiles(const std::string& path, + SignatureFileInfoSet& file) +{ + SignatureFileInfoSet signatureFiles; + SignatureFinder signatureFinder(path); + if (SignatureFinder::NO_ERROR != signatureFinder.find(file)) { + _E("Error in Signature Finder : %s", path.c_str()); + ThrowMsg(Exceptions::SignatureNotFound, "Signature not found"); + } +} + +TaskCertifyLevel::Level TaskCertifyLevel::getCertifyLevel() +{ + std::string widgetPath = m_contextData.locations->getPackageInstallationDir() + "/"; + SignatureFileInfoSet signatureFiles; + + Try { + getSignatureFiles(widgetPath, signatureFiles); + + if (signatureFiles.size() <= 0) { + widgetPath += std::string(WrtDB::GlobalConfig::GetWidgetSrcPath()) + + "/"; + if (0 == access(widgetPath.c_str(), F_OK)) { + getSignatureFiles(widgetPath, signatureFiles); + } + } + } Catch(Exceptions::SignatureNotFound) { + ReThrowMsg(Exceptions::SignatureNotFound, widgetPath); + } + + SignatureFileInfoSet::reverse_iterator iter = signatureFiles.rbegin(); + _D("Number of signatures: %d", signatureFiles.size()); + + Level level = Level::UNKNOWN; + for (; iter != signatureFiles.rend(); ++iter) { + _D("Checking signature with id=%d", iter->getFileNumber()); + SignatureData data(widgetPath + iter->getFileName(), + iter->getFileNumber()); + + Try { + SignatureReader xml; + xml.initialize(data, GlobalConfig::GetSignatureXmlSchema()); + xml.read(data); + + WrtSignatureValidator validator( + WrtSignatureValidator::TIZEN, + !GlobalSettings:: + OCSPTestModeEnabled(), + !GlobalSettings:: + CrlTestModeEnabled(), + false); + + WrtSignatureValidator::Result result = + validator.check(data, widgetPath); + + if (m_contextData.mode.installTime == InstallMode::InstallTime::PRELOAD + || m_contextData.mode.command == InstallMode::Command::RECOVERY + || m_contextData.mode.installTime == InstallMode::InstallTime::FOTA) + { + result = WrtSignatureValidator::SIGNATURE_VERIFIED; + } + + if (result == WrtSignatureValidator::SIGNATURE_REVOKED) { + ThrowMsg(Exceptions::CertificateExpired, + "Certificate is REVOKED"); + } + + if (result == WrtSignatureValidator::SIGNATURE_INVALID && + iter->getFileNumber() <= 1) + { + ThrowMsg(Exceptions::SignatureInvalid, "Invalid Package"); + } + + if (data.isAuthorSignature()) { + _D("Skip author signature"); + } else { + Level currentCertLevel = + certTypeToLevel(data.getVisibilityLevel()); + if (currentCertLevel == Level::UNKNOWN) { + continue; + } + if (currentCertLevel > level) { + level = currentCertLevel; + _D("level %s", enumToString(level).c_str()); + } + } + } Catch(ParserSchemaException::Base) { + _E("Error occured in ParserSchema."); + ReThrowMsg(Exceptions::SignatureInvalid, + "Error occured in ParserSchema."); + } + } + + m_contextData.certLevel = level; + return level; +} + +bool TaskCertifyLevel::checkConfigurationLevel( + TaskCertifyLevel::Level level) +{ + if (!checkSettingLevel(level)) { + return false; + } + if (!checkAppcontrolHasDisposition(level)) { + return false; + } + if (!checkServiceLevel(level)) { + return false; + } + return true; +} + +bool TaskCertifyLevel::checkSettingLevel( + TaskCertifyLevel::Level level) +{ + secureSettingMap data = { + {"sound-mode", Level::PARTNER}, + {"nodisplay", Level::PARTNER} + }; + FOREACH(it, m_contextData.widgetConfig.configInfo.settingsList) { + secureSettingIter ret = data.find(DPL::ToUTF8String(it->m_name)); + if (ret != data.end()) { + if (level < ret->second) { + _E("\"%ls\" needs \"%s\" level", it->m_name.c_str(), enumToString(ret->second).c_str()); + return false; + } + } + } + return true; +} + +bool TaskCertifyLevel::checkAppcontrolHasDisposition( + TaskCertifyLevel::Level level) +{ + // tizen:disposition -> platform + FOREACH(it, m_contextData.widgetConfig.configInfo.appControlList) { + if (ConfigParserData::AppControlInfo::Disposition::UNDEFINE != + it->m_disposition) + { + if (level < Level::PLATFORM) { + _E("\"tizen:disposition\" needs \"%s \" level", enumToString(Level::PLATFORM).c_str()); + return false; + } + } + } + return true; +} + +bool TaskCertifyLevel::checkServiceLevel( + TaskCertifyLevel::Level level) +{ + if (m_contextData.widgetConfig.configInfo.serviceAppInfoList.size() > 0) { + if (level < Level::PARTNER) { + _E("\"tizen:service\" needs \"%s \" level", enumToString(Level::PARTNER).c_str()); + return false; + } + } + return true; +} + +std::string TaskCertifyLevel::enumToString( + TaskCertifyLevel::Level level) +{ + switch (level) { +#define X(x, y) case x: return #y; + X(Level::UNKNOWN, UNKNOWN) + X(Level::PUBLIC, PUBLIC) + X(Level::PARTNER, PARTNER) + X(Level::PLATFORM, PLATFORM) +#undef X + default: + return "UNKNOWN"; + } +} + +TaskCertifyLevel::Level TaskCertifyLevel::certTypeToLevel( + CertStoreId::Type type) +{ + // CertStoreType.h (framework/security/cert-svc) + // RootCA's visibility level : public + // const Type VIS_PUBLIC = 1 << 6; + // RootCA's visibility level : partner + // const Type VIS_PARTNER = 1 << 7; + // RootCA's visibility level : platform + // const Type VIS_PLATFORM = 1 << 10; + if (type == CertStoreId::VIS_PUBLIC) { + return Level::PUBLIC; + } else if (type == CertStoreId::VIS_PARTNER) { + return Level::PARTNER; + } else if (type == CertStoreId::VIS_PLATFORM) { + return Level::PLATFORM; + } + return Level::UNKNOWN; +} + +void TaskCertifyLevel::StartStep() +{ + LOGD("--------- : START ----------"); +} + +void TaskCertifyLevel::EndStep() +{ + LOGD("--------- : END ----------"); + + m_contextData.job->UpdateProgress( + InstallerContext::INSTALL_CERTIFY_LEVEL_CHECK, + "Application Certificate level check Finished"); +} +} //namespace WidgetInstall +} //namespace Jobs + diff --git a/src_wearable/jobs/widget_install/task_certify_level.h b/src_wearable/jobs/widget_install/task_certify_level.h new file mode 100755 index 0000000..004ecbb --- /dev/null +++ b/src_wearable/jobs/widget_install/task_certify_level.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file task_certify_level.h + * @author Jihoon Chung (jihoon.chung@samgsung.com) + * @version + * @brief + */ +#ifndef INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_CERTIFY_LEVEL_H +#define INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_CERTIFY_LEVEL_H + +//SYSTEM INCLUDES +#include +#include +#include + +//WRT INCLUDES +#include +#include +#include + +class InstallerContext; + +namespace Jobs { +namespace WidgetInstall { +class TaskCertifyLevel : + public DPL::TaskDecl +{ + public: + TaskCertifyLevel(InstallerContext &inCont); + + private: + //data + InstallerContext& m_contextData; + + enum Level { + UNKNOWN = 0, + PUBLIC = 1, + PARTNER = 2, + PLATFORM = 3 + }; + typedef std::map secureSettingMap; + typedef std::map::iterator secureSettingIter; + + //steps + void stepCertifyLevel(); + void StartStep(); + void EndStep(); + + //util + void getSignatureFiles(const std::string& path, + ValidationCore::SignatureFileInfoSet& file); + Level getCertifyLevel(); + bool checkConfigurationLevel(Level level); + bool checkSettingLevel(Level level); + bool checkAppcontrolHasDisposition(Level level); + bool checkServiceLevel(Level level); + std::string enumToString(Level level); + Level certTypeToLevel(ValidationCore::CertStoreId::Type type); + +}; +} //namespace WidgetInstall +} //namespace Jobs + +#endif // INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_CERTIFY_LEVEL_H diff --git a/src_wearable/jobs/widget_install/task_commons.cpp b/src_wearable/jobs/widget_install/task_commons.cpp new file mode 100644 index 0000000..c5b5b67 --- /dev/null +++ b/src_wearable/jobs/widget_install/task_commons.cpp @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file task_commons.cpp + * @author Krzysztof Jackiewicz (k.jackiewicz@samsung.com) + * @version 1.0 + */ + +#include "task_commons.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Jobs { +namespace WidgetInstall { +namespace { +const char * const TEMPORARY_PATH_POSTFIX = "temp"; +const mode_t TEMPORARY_PATH_MODE = 0775; +} // namespace + +std::string createTempPath(bool preload) +{ + _D("Step: Creating temporary path"); + + // Temporary path + std::ostringstream tempPathBuilder; + + if (preload) { + tempPathBuilder << WrtDB::GlobalConfig::GetUserPreloadedWidgetPath(); + } else { + tempPathBuilder << WrtDB::GlobalConfig::GetUserInstalledWidgetPath(); + } + tempPathBuilder << WrtDB::GlobalConfig::GetTmpDirPath(); + tempPathBuilder << "/"; + tempPathBuilder << TEMPORARY_PATH_POSTFIX; + tempPathBuilder << "_"; + + timeval tv; + gettimeofday(&tv, NULL); + tempPathBuilder << + (static_cast(tv.tv_sec) * 1000000ULL + + static_cast(tv.tv_usec)); + + std::string tempPath = tempPathBuilder.str(); + + // Remove old path if any + struct stat fileInfo; + + if (stat(tempPath.c_str(), &fileInfo) == 0) { + if (!WrtUtilRemove(tempPath)) { + ThrowMsg(Exceptions::RemovingFolderFailure, + "Failed to to remove temporary directory"); + } + } + // Create new path + if (!WrtUtilMakeDir(tempPath, TEMPORARY_PATH_MODE)) { + ThrowMsg(Exceptions::FileOperationFailed, + "Failed to create temporary directory"); + } + + return tempPath; +} + +void createTempPath(const std::string& path) +{ + if (!WrtUtilMakeDir(path, TEMPORARY_PATH_MODE)) { + ThrowMsg(Exceptions::FileOperationFailed, + "Failed to create temporary directory"); + } +} +} // WidgetInstall +} // Jobs diff --git a/src_wearable/jobs/widget_install/task_commons.h b/src_wearable/jobs/widget_install/task_commons.h new file mode 100644 index 0000000..caf9660 --- /dev/null +++ b/src_wearable/jobs/widget_install/task_commons.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file task_commons.h + * @author Krzysztof Jackiewicz (k.jackiewicz@samsung.com) + * @version 1.0 + */ + +#ifndef INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_COMMONS_H_ +#define INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_COMMONS_H_ + +#include + +namespace Jobs { +namespace WidgetInstall { +//TODO make directory like jobs common? + +std::string createTempPath(bool isReadOnly = false); +void createTempPath(const std::string& path); +} // WidgetInstall +} // Jobs + +#endif /* INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_COMMONS_H_ */ diff --git a/src_wearable/jobs/widget_install/task_configuration.cpp b/src_wearable/jobs/widget_install/task_configuration.cpp new file mode 100755 index 0000000..fa3e0fa --- /dev/null +++ b/src_wearable/jobs/widget_install/task_configuration.cpp @@ -0,0 +1,610 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file task_configuration.cpp + * @version 1.0 + * @author Tomasz Iwanek + * @brief implementation file for configuration task + */ +#include "task_configuration.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "root_parser.h" +#include "widget_parser.h" +#include "parser_runner.h" + +#include +#include +#include +#include +#include +#include +#include + +using namespace WrtDB; + +namespace { +const char* const CONFIG_XML = "config.xml"; +const char* const WITH_OSP_XML = "res/wgt/config.xml"; +const char* const OSP_MANIFEST_XML = "info/manifest.xml"; +const char* const WRT_WIDGETS_XML_SCHEMA = "/usr/etc/wrt-installer/widgets.xsd"; + +//allowed: a-z, A-Z, 0-9 +const char* REG_TIZENID_PATTERN = "^[a-zA-Z0-9]{10}.{1,}$"; +const char* REG_PKGID_PATTERN = "^[a-zA-Z0-9]{10}$"; +const char* REG_NAME_PATTERN = "^[a-zA-Z0-9._-]{1,}$"; +const size_t PACKAGE_ID_LENGTH = 10; + +static const DPL::String SETTING_VALUE_ENCRYPTION = L"encryption"; +static const DPL::String SETTING_VALUE_ENCRYPTION_ENABLE = L"enable"; +static const DPL::String SETTING_VALUE_ENCRYPTION_DISABLE = L"disable"; +const DPL::String SETTING_VALUE_INSTALLTOEXT_NAME = L"install-location"; +const DPL::String SETTING_VALUE_INSTALLTOEXT_PREPER_EXT = L"prefer-external"; +const DPL::String SETTING_VALUE_INSTALLTOEXT_AUTO = L"auto"; +const std::string XML_EXTENSION = ".xml"; + +bool hasExtension(const std::string& filename, const std::string& extension) +{ + _D("Looking for extension %s in %s", extension.c_str(), filename.c_str()); + size_t fileLen = filename.length(); + size_t extLen = extension.length(); + if (fileLen < extLen) { + _E("Filename %s is shorter than extension %s", filename.c_str(), extension.c_str()); + return false; + } + return (0 == filename.compare(fileLen - extLen, extLen, extension)); +} +} // namespace anonymous + +namespace Jobs { +namespace WidgetInstall { + +TaskConfiguration::TaskConfiguration(InstallerContext& context) : + DPL::TaskDecl(this), + m_context(context), + m_widgetConfig(m_context.widgetConfig.configInfo) +{ + AddStep(&TaskConfiguration::StartStep); + + AddStep(&TaskConfiguration::SetupTempDirStep); + AddStep(&TaskConfiguration::UnzipConfigurationStep); + AddStep(&TaskConfiguration::ParseXMLConfigStep); + + AddStep(&TaskConfiguration::TizenIdStep); + AddStep(&TaskConfiguration::ApplicationTypeStep); + AddStep(&TaskConfiguration::ResourceEncryptionStep); + AddStep(&TaskConfiguration::InstallationFSLocationStep); + + AddStep(&TaskConfiguration::DetectUpdateInstallationStep); + AddStep(&TaskConfiguration::CheckRDSSupportStep); + AddStep(&TaskConfiguration::ConfigureWidgetLocationStep); + AddStep(&TaskConfiguration::PkgmgrStartStep); + + AddStep(&TaskConfiguration::AppendTasklistStep); + + AddStep(&TaskConfiguration::EndStep); +} + +void TaskConfiguration::StartStep() +{ + LOGD("--------- : START ----------"); +} + +void TaskConfiguration::EndStep() +{ + m_context.job->UpdateProgress(InstallerContext::INSTALL_PARSE_CONFIG, + "Parse config.xml and set structure"); + LOGD("--------- : END ----------"); +} + +void TaskConfiguration::PkgmgrStartStep() +{ + pkgMgrInterface()->setPkgname(DPL::ToUTF8String(m_context.widgetConfig.tzPkgid)); + pkgMgrInterface()->sendProgress(0); +} + +void TaskConfiguration::AppendTasklistStep() +{ + switch(m_context.widgetConfig.webAppType.appType) + { + case APP_TYPE_TIZENWEBAPP: + if (m_context.mode.installTime == InstallMode::InstallTime::FOTA) { + if (!m_context.isUpdateMode) { + _D("TaskConfiguration -> fota installation task list"); + m_context.job->appendFotaInstallationTaskList(); + } else { + _D("TaskConfiguration -> fota update task list"); + m_context.job->appendFotaUpdateTaskList(); + } + } else { + if (!m_context.isUpdateMode) { + _D("TaskConfiguration -> new installation task list"); + m_context.job->appendNewInstallationTaskList(); + } else { + if (m_context.mode.command == InstallMode::Command::REINSTALL) { + _D("TaskConfiguration -> rds update task list"); + m_context.job->appendRDSUpdateTaskList(); + } else if(m_context.mode.command == InstallMode::Command::RECOVERY) { + _D("TaskConfiguration -> recovery task list"); + m_context.job->appendRecoveryTaskList(); + } else { + _D("TaskConfiguration -> update installation task list"); + m_context.job->appendUpdateInstallationTaskList(); + } + } + } + break; + default: + ThrowMsg(Jobs::WidgetInstall::Exceptions::WidgetConfigFileInvalid, "Unknown application type"); + } +} + +std::shared_ptr TaskConfiguration::pkgMgrInterface() +{ + return m_context.job->GetInstallerStruct().pkgmgrInterface; +} + +void TaskConfiguration::SetupTempDirStep() +{ + _D("widgetPath: %s", m_context.requestedPath.c_str()); + _D("tempPath: %s", m_tempDir.c_str()); + if (m_context.mode.extension == InstallMode::ExtensionType::DIR) { + if (m_context.mode.command == + InstallMode::Command::REINSTALL) { + std::ostringstream tempPathBuilder; + tempPathBuilder << WrtDB::GlobalConfig::GetUserInstalledWidgetPath(); + tempPathBuilder << WrtDB::GlobalConfig::GetTmpDirPath(); + tempPathBuilder << "/"; + tempPathBuilder << m_context.requestedPath; + m_tempDir = tempPathBuilder.str(); + } else if(m_context.mode.command == InstallMode::Command::RECOVERY) { + m_tempDir = Jobs::WidgetInstall::createTempPath(false); + } else { + m_tempDir = m_context.requestedPath; + } + } else { + m_tempDir = + Jobs::WidgetInstall::createTempPath( + m_context.mode.rootPath == + InstallMode::RootPath::RO); + } +} + +void TaskConfiguration::UnzipConfigurationStep() +{ + _D("UnzipConfigurationStep"); + if (m_context.mode.extension != InstallMode::ExtensionType::DIR) { + if(!hasExtension(m_context.requestedPath, XML_EXTENSION)) //unzip everything except xml files + { + WidgetUnzip wgtUnzip(m_context.requestedPath); + wgtUnzip.unzipConfiguration(m_tempDir, &m_context.widgetConfig.packagingType); + m_configuration += m_tempDir + "/" + CONFIG_XML; + } else{ + m_context.widgetConfig.packagingType = PKG_TYPE_HOSTED_WEB_APP; + m_configuration += m_context.requestedPath; + } + } else { + std::string configFile = m_tempDir + "/" + CONFIG_XML; + std::string manifestFile = m_tempDir + "/"; + if (!WrtUtilFileExists(configFile)) { + configFile = m_tempDir + "/" + WITH_OSP_XML; + if (!WrtUtilFileExists(configFile)) { + std::string tzAppId = m_context.requestedPath. + substr(m_context.requestedPath.find_last_of("/")+1); + Try { + WidgetDAOReadOnly dao(WidgetDAOReadOnly::getTizenAppId(DPL::FromUTF8String(tzAppId))); + configFile = DPL::ToUTF8String(*dao.getWidgetInstalledPath()); + configFile += "/"; + manifestFile = configFile; + configFile += WITH_OSP_XML; + } + Catch(WidgetDAOReadOnly::Exception::WidgetNotExist) + { + _E("Given tizenId not found in database"); + ThrowMsg(Exceptions::DatabaseFailure, "Given tizenId not found in database"); + } + } + } + m_context.widgetConfig.packagingType = PKG_TYPE_NOMAL_WEB_APP; + manifestFile += OSP_MANIFEST_XML; + + if (WrtUtilFileExists(manifestFile)) { + m_context.widgetConfig.packagingType = PKG_TYPE_HYBRID_WEB_APP; + } + m_configuration = configFile; + } + _D("m_configuration : %s", m_configuration.c_str()); + _D("Package Type : %s", m_context.widgetConfig.packagingType.getPkgtypeToString().c_str()); +} + +void TaskConfiguration::ParseXMLConfigStep() +{ + _D("ParseXMLConfigStep"); + // Parse config + ParserRunner parser; + Try + { + _D("m_configuration : %s", m_configuration.c_str()); + if(!DPL::Utils::Path(m_configuration).Exists()) + { + ThrowMsg(Exceptions::MissingConfig, "Config file not exists"); + } + +#ifdef SCHEMA_VALIDATION_ENABLED + if(!parser.Validate(m_configuration, WRT_WIDGETS_XML_SCHEMA)) + { + _E("Invalid configuration file - schema validation failed"); + ThrowMsg(Exceptions::WidgetConfigFileInvalid, "Failed to parse config.xml file"); + } +#endif + parser.Parse(m_configuration, + ElementParserPtr( + new RootParser(m_widgetConfig, + DPL:: + FromUTF32String( + L"widget")))); + } + Catch(ElementParser::Exception::ParseError) + { + _E("Failed to parse config.xml file"); + ThrowMsg(Exceptions::WidgetConfigFileInvalid, "Parser exeption"); + } + Catch(WidgetDAOReadOnly::Exception::WidgetNotExist) + { + _E("Failed to find installed widget - give proper tizenId"); + ThrowMsg(Exceptions::RDSDeltaFailure, "WidgetNotExist"); + } + Catch(Exceptions::WidgetConfigFileNotFound){ + _E("Failed to find config.xml"); + ThrowMsg(Exceptions::MissingConfig, "Parser exeption"); + } + + if (m_context.mode.extension != InstallMode::ExtensionType::DIR) { + if (!WrtUtilRemove(m_configuration)) { + _E("Error occurs during removing %s", m_configuration.c_str()); + } + } + +} + +void TaskConfiguration::TizenIdStep() +{ + bool shouldMakeAppid = false; + using namespace PackageManager; + + if (!!m_widgetConfig.tizenAppId) { + _D("Setting tizenAppId provided in config.xml: %s", DPL::ToUTF8String(*m_widgetConfig.tizenAppId).c_str()); + + m_context.widgetConfig.tzAppid = *m_widgetConfig.tizenAppId; + //check package id. + if (!!m_widgetConfig.tizenPkgId) { + _D("Setting tizenPkgId provided in config.xml: %s", DPL::ToUTF8String(*m_widgetConfig.tizenPkgId).c_str()); + + m_context.widgetConfig.tzPkgid = *m_widgetConfig.tizenPkgId; + } else { + DPL::String appid = *m_widgetConfig.tizenAppId; + if (appid.length() > PACKAGE_ID_LENGTH) { + m_context.widgetConfig.tzPkgid = + appid.substr(0, PACKAGE_ID_LENGTH); + } else { + //old version appid only has 10byte random character is able to install for a while. + //this case appid equal pkgid. + m_context.widgetConfig.tzPkgid = + *m_widgetConfig.tizenAppId; + shouldMakeAppid = true; + } + } + } else { + shouldMakeAppid = true; + TizenPkgId pkgId = WidgetDAOReadOnly::generatePkgId(); + _D("Checking if pkg id is unique"); + while (true) { + if (!validateTizenPackageID(pkgId)) { + //path exist, chose another one + pkgId = WidgetDAOReadOnly::generatePkgId(); + continue; + } + break; + } + m_context.widgetConfig.tzPkgid = pkgId; + _D("tizen_id name was generated by WRT: %ls", m_context.widgetConfig.tzPkgid.c_str()); + } + + if (shouldMakeAppid == true) { + DPL::OptionalString name; + DPL::OptionalString defaultLocale = m_widgetConfig.defaultlocale; + + FOREACH(localizedData, m_widgetConfig.localizedDataSet) + { + Locale i = localizedData->first; + if (!!defaultLocale) { + if (defaultLocale == i) { + name = localizedData->second.name; + break; + } + } else { + name = localizedData->second.name; + break; + } + } + regex_t regx; + if (regcomp(®x, REG_NAME_PATTERN, REG_NOSUB | REG_EXTENDED) != 0) { + _D("Regcomp failed"); + } + + _D("Name : %ls", (*name).c_str()); + if (!name || (regexec(®x, DPL::ToUTF8String(*name).c_str(), + static_cast(0), NULL, 0) != REG_NOERROR)) + { + const std::string allowedString("ABCDEFGHIJKLMNOPQRSTUVWXYZ"); + std::ostringstream genName; + struct timeval tv; + gettimeofday(&tv, NULL); + unsigned int seed = time(NULL) + tv.tv_usec; + + genName << "_" << allowedString[rand_r(&seed) % allowedString.length()]; + name = DPL::FromUTF8String(genName.str()); + _D("name was generated by WRT"); + } + regfree(®x); + _D("Name : %ls", (*name).c_str()); + std::ostringstream genid; + genid << m_context.widgetConfig.tzPkgid << "." << (*name); + _D("tizen appid was generated by WRT : %s", genid.str().c_str()); + + DPL::OptionalString appid = DPL::FromUTF8String(genid.str()); + NormalizeAndTrimSpaceString(appid); + m_context.widgetConfig.tzAppid = *appid; + } + + // send start signal of pkgmgr + pkgMgrInterface()->setPkgname(DPL::ToUTF8String(m_context.widgetConfig.tzPkgid)); + + _D("Tizen App Id : %ls", (m_context.widgetConfig.tzAppid).c_str()); + _D("Tizen Pkg Id : %ls", (m_context.widgetConfig.tzPkgid).c_str()); +} + +void TaskConfiguration::ConfigureWidgetLocationStep() +{ + m_context.locations = + WidgetLocation(DPL::ToUTF8String(m_context.widgetConfig.tzPkgid), + m_context.requestedPath, m_tempDir, + m_context.widgetConfig.packagingType, + m_context.mode.rootPath == + InstallMode::RootPath::RO, + m_context.mode.extension); + m_context.locations->registerAppid( + DPL::ToUTF8String(m_context.widgetConfig.tzAppid)); +#ifdef SERVICE_ENABLED + FOREACH(it, m_context.widgetConfig.configInfo.serviceAppInfoList) + { + m_context.locations->registerServiceAppid(DPL::ToUTF8String(it->serviceId)); + } +#endif + _D("widgetSource %s", m_context.requestedPath.c_str()); +} + +void TaskConfiguration::DetectUpdateInstallationStep() +{ + pkgmgrinfo_pkginfo_h handle; + + if (PMINFO_R_OK == + pkgmgrinfo_pkginfo_get_pkginfo(DPL::ToUTF8String( + m_context.widgetConfig.tzPkgid).c_str(), &handle)) { + // Update mode + m_context.isUpdateMode = true; + pkgMgrInterface()->startJob(InstallationType::UpdateInstallation); + + } else { + // Install mode + m_context.isUpdateMode = false; + pkgMgrInterface()->startJob(InstallationType::NewInstallation); + + if (!validateTizenApplicationID(m_context.widgetConfig.tzAppid)) { + _E("tizen application ID is invalid"); + ThrowMsg(Jobs::WidgetInstall::Exceptions::WidgetConfigFileInvalid, + "invalid config"); + } + if (!validateTizenPackageID(m_context.widgetConfig.tzPkgid)) { + _E("tizen package ID is invalid"); + ThrowMsg(Jobs::WidgetInstall::Exceptions::WidgetConfigFileInvalid, + "invalid config"); + } + } + OptionalWidgetVersion incomingVersion; + char *existingVersion = NULL; + + if (!!m_widgetConfig.version) { + incomingVersion = + OptionalWidgetVersion( + WidgetVersion(*m_widgetConfig.version)); + _D("incoming version = '%ls", incomingVersion->Raw().c_str()); + } + + if (m_context.isUpdateMode && + PMINFO_R_OK == pkgmgrinfo_pkginfo_get_version(handle, + &existingVersion)) { + _D("existing version = %s", existingVersion); + } + + pkgmgrinfo_pkginfo_destroy_pkginfo(handle); +} + +void TaskConfiguration::CheckRDSSupportStep() +{ + //update needs RDS support to go ahead if REINSTALL command is given + if(m_context.isUpdateMode) + { + if (!checkSupportRDSUpdateIfReinstall(m_widgetConfig)) { + ThrowMsg(Jobs::WidgetInstall::Exceptions::NotSupportRDSUpdate, + "RDS update failed"); + } + } +} + +bool TaskConfiguration::validateTizenApplicationID( + const WrtDB::TizenAppId &tizenAppId) +{ + _D("tizen application ID = [%ls]", tizenAppId.c_str()); + + regex_t reg; + if (regcomp(®, REG_TIZENID_PATTERN, REG_NOSUB | REG_EXTENDED) != 0) { + _D("Regcomp failed"); + return false; + } + + if (regexec(®, DPL::ToUTF8String(tizenAppId).c_str(), 0, NULL, 0) + == REG_NOMATCH) + { + regfree(®); + return false; + } + regfree(®); + return true; +} + +bool TaskConfiguration::validateTizenPackageID( + const WrtDB::TizenPkgId &tizenPkgId) +{ + _D("tizen application ID = [%ls]", tizenPkgId.c_str()); + + regex_t reg; + if (regcomp(®, REG_PKGID_PATTERN, REG_NOSUB | REG_EXTENDED) != 0) + { + _D("Regcomp failed"); + return false; + } + if (regexec(®, DPL::ToUTF8String(tizenPkgId).c_str(), 0, NULL, 0) == REG_NOMATCH) + { + regfree(®); + return false; + } + regfree(®); + return true; +} + +void TaskConfiguration::ApplicationTypeStep() //TODO: is this really needed as WAC is not supported? +{ + AppType widgetAppType = APP_TYPE_UNKNOWN; + FOREACH(iterator, m_widgetConfig.nameSpaces) { + _D("namespace = [%ls]", (*iterator).c_str()); + + if (*iterator == ConfigurationNamespace::TizenWebAppNamespaceName) { + widgetAppType = APP_TYPE_TIZENWEBAPP; + break; + } + } + + m_context.widgetConfig.webAppType = widgetAppType; + + _D("type = [%s]", m_context.widgetConfig.webAppType.getApptypeToString().c_str()); +} + +void TaskConfiguration::ResourceEncryptionStep() +{ + m_context.needEncryption = false; + FOREACH(it, m_widgetConfig.settingsList) + { + if (it->m_name == SETTING_VALUE_ENCRYPTION && + it->m_value == SETTING_VALUE_ENCRYPTION_ENABLE) + { + _D("resource need encryption"); + m_context.needEncryption = true; + } + } +} + +void TaskConfiguration::InstallationFSLocationStep() +{ + if (m_context.mode.installTime == InstallMode::InstallTime::NORMAL) { + FOREACH(it, m_widgetConfig.settingsList) { + if (it->m_name == SETTING_VALUE_INSTALLTOEXT_NAME) { + if (it->m_value == SETTING_VALUE_INSTALLTOEXT_AUTO) { + m_context.locationType = INSTALL_LOCATION_TYPE_AUTO; + } else if (it->m_value == SETTING_VALUE_INSTALLTOEXT_PREPER_EXT) { + m_context.locationType = + INSTALL_LOCATION_TYPE_PREFER_EXTERNAL; + } else { + m_context.locationType = + INSTALL_LOCATION_TYPE_INTERNAL_ONLY; + } + break; + } + } + } else { + m_context.locationType = INSTALL_LOCATION_TYPE_INTERNAL_ONLY; + } +} + +bool TaskConfiguration::checkSupportRDSUpdateIfReinstall(const WrtDB::ConfigParserData + &configInfo) +{ + if (m_context.mode.command == + InstallMode::Command::REINSTALL) + { + DPL::String configValue = SETTING_VALUE_ENCRYPTION_DISABLE; + DPL::String dbValue = SETTING_VALUE_ENCRYPTION_DISABLE; + + WidgetDAOReadOnly dao(m_context.widgetConfig.tzAppid); + WrtDB::WidgetSettings widgetSettings; + dao.getWidgetSettings(widgetSettings); + + FOREACH(it, widgetSettings) { + if (it->settingName == SETTING_VALUE_ENCRYPTION) { + dbValue = it->settingValue; + } + } + + FOREACH(data, configInfo.settingsList) + { + if (data->m_name == SETTING_VALUE_ENCRYPTION) + { + configValue = data->m_value; + } + } + if (configValue != dbValue) { + _E("Not Support RDS mode because of encryption setting"); + return false; + } + } + + return true; +} + +} +} diff --git a/src_wearable/jobs/widget_install/task_configuration.h b/src_wearable/jobs/widget_install/task_configuration.h new file mode 100644 index 0000000..879a8d3 --- /dev/null +++ b/src_wearable/jobs/widget_install/task_configuration.h @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file task_configuration.h + * @version 1.0 + * @author Tomasz Iwanek + * @brief header file for configuration task + */ +#ifndef TASK_CONFIGURATION_H +#define TASK_CONFIGURATION_H + +#include + +#include +#include + +#include +#include + +#include + +class InstallerContext; + +namespace Jobs { +namespace WidgetInstall { + +class TaskConfiguration : public DPL::TaskDecl +{ + InstallerContext& m_context; + std::string m_tempDir; + WrtDB::ConfigParserData &m_widgetConfig; + std::string m_configuration; + + void parseWidgetXMLConfig( + const std::string &widgetSource, + const std::string &tempPath, + WrtDB::PackagingType pkgType, + bool isReinstall); + + bool validateTizenApplicationID(const WrtDB::TizenAppId &tizenAppId); + bool validateTizenPackageID(const WrtDB::TizenPkgId &tizenPkgId); + void ApplicationTypeStep(const WrtDB::ConfigParserData &configInfo); + bool checkSupportRDSUpdateIfReinstall(const WrtDB::ConfigParserData &configInfo); + bool getDefaultExternalStorage(); + bool getMMCStatus(); + + std::shared_ptr pkgMgrInterface(); + + //steps + void StartStep(); + + void SetupTempDirStep(); + void UnzipConfigurationStep(); + void ParseXMLConfigStep(); + + void TizenIdStep(); + void DetectUpdateInstallationStep(); + void PkgmgrStartStep(); + + void ApplicationTypeStep(); + void ResourceEncryptionStep(); + void InstallationFSLocationStep(); + + void ConfigureWidgetLocationStep(); + void CheckRDSSupportStep(); + + void AppendTasklistStep(); + void EndStep(); + +public: + TaskConfiguration(InstallerContext& context); +}; + +} +} + +#endif // TASK_CONFIGURATION_H diff --git a/src_wearable/jobs/widget_install/task_database.cpp b/src_wearable/jobs/widget_install/task_database.cpp new file mode 100755 index 0000000..8b9660b --- /dev/null +++ b/src_wearable/jobs/widget_install/task_database.cpp @@ -0,0 +1,430 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file task_new_db_insert.cpp + * @author Lukasz Wrzosek(l.wrzosek@samsung.com) + * @author Soyoung kim(sy037.kim@samsung.com) + * @version 1.0 + * @brief Implementation file for installer task database updating for widget + * update + */ +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef DBOX_ENABLED +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace WrtDB; + +namespace Jobs { +namespace WidgetInstall { +TaskDatabase::TaskDatabase(InstallerContext& context) : + DPL::TaskDecl(this), + m_context(context) +{ + AddStep(&TaskDatabase::StartStep); + AddStep(&TaskDatabase::StepRegisterExternalFiles); + AddStep(&TaskDatabase::StepWrtDBInsert); + AddStep(&TaskDatabase::StepAceDBInsert); + AddStep(&TaskDatabase::StepSecurityOriginDBInsert); + AddStep(&TaskDatabase::StepWidgetInterfaceDBInsert); + AddStep(&TaskDatabase::StepRemoveExternalFiles); +#ifdef DBOX_ENABLED + AddStep(&TaskDatabase::StepLiveboxDBInsert); +#endif + AddStep(&TaskDatabase::EndStep); + + AddAbortStep(&TaskDatabase::StepAbortDBInsert); + AddAbortStep(&TaskDatabase::StepAbortAceDBInsert); + AddAbortStep(&TaskDatabase::StepAbortWidgetInterfaceDBInsert); +} + +void TaskDatabase::StepWrtDBInsert() +{ + Try + { + /* Set install Time */ + time(&m_context.widgetConfig.installedTime); + + if (m_context.isUpdateMode) { //update + _D("Registering widget... (update)"); + Try + { + std::list idList = WidgetDAOReadOnly::getTzAppIdList(m_context.widgetConfig.tzPkgid); + FOREACH(it , idList ){ + //installed AppId list, It need to delete ACE Database corresponding record + m_handleToRemoveList.push_back(WidgetDAOReadOnly::getHandle(*it)); + WrtDB::TizenAppId backAppId = *it + L".backup"; + m_backAppIdList.push_back(backAppId); + //Change all installed tzAppid to .backup + WidgetDAO::updateTizenAppId(*it, backAppId); + } + + WidgetDAO::registerWidget(m_context.widgetConfig.tzAppid, + m_context.widgetConfig, + m_context.widgetSecurity); + m_handleList.push_back(WidgetDAOReadOnly::getHandle(m_context.widgetConfig.tzAppid)); + + FOREACH(iterator, m_context.widgetConfig.configInfo.serviceAppInfoList) { + WrtDB::TizenAppId tizenAppId = iterator->serviceId; + WidgetDAO::registerService(*iterator, m_context.widgetConfig, m_context.widgetSecurity); + m_handleList.push_back(WidgetDAOReadOnly::getHandle(tizenAppId)); + } + } + Catch(WidgetDAOReadOnly::Exception::WidgetNotExist) + { + LogError( + "Given tizenId not found for update installation (Same GUID?)"); + ThrowMsg(Exceptions::DatabaseFailure, + "Given tizenId not found for update installation"); + } + } else { //new installation + _D("Registering widget..."); + WidgetDAO::registerWidget( + m_context.widgetConfig.tzAppid, + m_context.widgetConfig, + m_context.widgetSecurity); + + m_handleList.push_back(WidgetDAOReadOnly::getHandle(m_context.widgetConfig.tzAppid)); + + FOREACH(iterator, m_context.widgetConfig.configInfo.serviceAppInfoList) { + WidgetDAO::registerService(*iterator, m_context.widgetConfig, m_context.widgetSecurity); + m_handleList.push_back(WidgetDAOReadOnly::getHandle(iterator->serviceId)); + } + } + + FOREACH(cap, m_context.staticPermittedDevCaps) { + _D("staticPermittedDevCaps : %ls smack status: %d", cap->first.c_str(), cap->second); + } + + _D("Widget registered"); + } + Catch(WidgetDAO::Exception::DatabaseError) + { + _E("Database failure!"); + ReThrowMsg(Exceptions::InsertNewWidgetFailed, "Database failure!"); + } + Catch(DPL::DB::SqlConnection::Exception::Base) + { + _E("Database failure!"); + ReThrowMsg(Exceptions::InsertNewWidgetFailed, "Database failure!"); + } +} + +void TaskDatabase::StepAceDBInsert() +{ + FOREACH(iterHandleToRemove, m_handleToRemoveList) + { + if (INVALID_WIDGET_HANDLE != *iterHandleToRemove) { + _D("Removing old insallation. Handle: %d", *iterHandleToRemove); + if (ACE_OK != ace_unregister_widget( + static_cast(*iterHandleToRemove))) + { + _W("Error while removing ace entry for previous insallation"); + } + } + } + + FOREACH(iterHandle, m_handleList) + { + if (!AceApi::registerAceWidget(*iterHandle, m_context.widgetConfig, + m_context.widgetSecurity.getCertificateList())) + { + _E("ace database insert failed"); + ThrowMsg(Exceptions::UpdateFailed, + "Update failure. ace_register_widget failed"); + } + _D("Ace data inserted"); + } +} + +void TaskDatabase::StepSecurityOriginDBInsert() +{ + _D("Create Security origin database"); + // automatically create security origin database + using namespace SecurityOriginDB; + using namespace WrtDB; + + try{ + SecurityOriginDAO dao(m_context.locations->getPkgId()); + // Checking privilege list for setting security origin exception data + FOREACH(it, m_context.widgetConfig.configInfo.privilegeList) { + std::map::const_iterator result = + g_W3CPrivilegeTextMap.find(DPL::ToUTF8String(it->name)); + if (result != g_W3CPrivilegeTextMap.end()) { + if (result->second == FEATURE_USER_MEDIA) { + dao.setPrivilegeSecurityOriginData(result->second, false); + } else if (result->second == FEATURE_FULLSCREEN_MODE) { + continue; + } else { + dao.setPrivilegeSecurityOriginData(result->second); + } + } + } + }catch(const SecurityOriginDAO::Exception::DatabaseError& err){ + _E("error open SecurityOrigin db %s", err.GetMessage().c_str()); + ThrowMsg(Exceptions::UpdateFailed, "Cannot open SecurityOrigin DB"); + } +} + +void TaskDatabase::StepWidgetInterfaceDBInsert() +{ + _D("Create Widget Interface database"); + using namespace WidgetInterfaceDB; + using namespace WrtDB; + + DbWidgetHandle handle = + WidgetDAOReadOnly::getHandle(m_context.widgetConfig.tzAppid); + + // backup database + if (m_context.isUpdateMode) { + std::string dbPath = WidgetInterfaceDAO::databaseFileName(handle); + std::string backupDbPath = dbPath; + backupDbPath += GlobalConfig::GetBackupDatabaseSuffix(); + _D("\"%s\" to \"%s\"", dbPath.c_str(), backupDbPath.c_str()); + if (0 != std::rename(dbPath.c_str(), backupDbPath.c_str())) { + _E("widget interface database backup failed"); + ThrowMsg(Exceptions::UpdateFailed, + "widget interface database backup failed"); + } + } + + Try + { + // automatically create widget interface database + WidgetInterfaceDAO dao(handle); + } + Catch(WidgetInterfaceDAO::Exception::DatabaseError) + { + _E("widget interface database create failed"); + ThrowMsg(Exceptions::UpdateFailed, + "widget interface database create failed"); + } +} + +void TaskDatabase::StepRegisterExternalFiles() +{ + WrtDB::ExternalLocationList externalLocationsUpdate = + m_context.locations->listExternalLocations(); + if (m_context.isUpdateMode) { //update + Try + { + WidgetDAOReadOnly dao(WidgetDAOReadOnly::getHandleByPkgId(m_context.widgetConfig.tzPkgid)); + WrtDB::ExternalLocationList externalLocationsDB = + dao.getWidgetExternalLocations(); + FOREACH(file, externalLocationsDB) + { + if (std::find(externalLocationsUpdate.begin(), + externalLocationsUpdate.end(), + *file) == externalLocationsUpdate.end()) + { + m_externalLocationsToRemove.push_back(*file); + } + } + } + Catch(WidgetDAOReadOnly::Exception::WidgetNotExist) + { + _E("Given tizenId not found for update installation (Same GUID?)"); + ThrowMsg(Exceptions::UpdateFailed, + "Given tizenId not found for update installation"); + } + } + _D("Registering external files:"); + FOREACH(file, externalLocationsUpdate) + { + _D(" -> %s", (*file).c_str()); + } + + //set external locations to be registered + m_context.widgetConfig.externalLocations = externalLocationsUpdate; +} + +void TaskDatabase::StepRemoveExternalFiles() +{ + if (!m_externalLocationsToRemove.empty()) { + _D("Removing external files:"); + } + + FOREACH(file, m_externalLocationsToRemove) + { + if (WrtUtilFileExists(*file)) { + _D(" -> %s", (*file).c_str()); + if (-1 == remove(file->c_str())) { + ThrowMsg(Exceptions::RemovingFileFailure, + "Failed to remove external file"); + } + } else if (WrtUtilDirExists(*file)) { + _D(" -> %s", (*file).c_str()); + if (!WrtUtilRemove(*file)) { + ThrowMsg(Exceptions::RemovingFolderFailure, + "Failed to remove external directory"); + } + } else { + _W(" -> %s(no such a path)", (*file).c_str()); + } + } +} + +void TaskDatabase::StepAbortDBInsert() +{ + _W("[DB Update Task] Aborting... (DB Clean)"); + Try + { + WidgetDAO::unregisterWidget(m_context.widgetConfig.tzAppid); + + FOREACH(iter, m_context.widgetConfig.configInfo.serviceAppInfoList) { + WidgetDAO::unregisterWidget(iter->serviceId); + } + + if (m_context.isUpdateMode) { + FOREACH(iter, m_backAppIdList) { + unsigned pos = (*iter).find(L".backup"); + TizenAppId str = (*iter).substr(0, pos); + WidgetDAO::updateTizenAppId(*iter, str); + } + } + _D("Cleaning DB successful!"); + } + Catch(DPL::DB::SqlConnection::Exception::Base) + { + _E("Failed to handle StepAbortDBClean!"); + } +} + +void TaskDatabase::StepAbortAceDBInsert() +{ + _W("[DB Update Task] ACE DB Aborting... (DB Clean)"); + + FOREACH(iter, m_handleList) { + ace_unregister_widget(static_cast(*iter)); + } + + FOREACH(iter, m_handleToRemoveList) { + // Remove also old one. If it was already updated nothing wrong will happen, + // but if not old widget will be removed. + if (INVALID_WIDGET_HANDLE != *iter) { + ace_unregister_widget(static_cast(*iter)); + } + + if (!AceApi::registerAceWidgetFromDB(*iter)) + { + _E("ace database restore failed"); + } + } + _D("Ace data inserted"); +} + +void TaskDatabase::StepAbortWidgetInterfaceDBInsert() +{ + _D("[DB Update Task] Widget interface Aborting..."); + using namespace WidgetInterfaceDB; + using namespace WrtDB; + + DbWidgetHandle handle = + WidgetDAOReadOnly::getHandle(m_context.widgetConfig.tzAppid); + std::string dbPath = WidgetInterfaceDAO::databaseFileName(handle); + + // remove database + if (remove(dbPath.c_str()) != 0) { + _W("Fail to remove"); + } + + // rollback database + if (m_context.isUpdateMode) { + std::string backupDbPath = dbPath; + backupDbPath += GlobalConfig::GetBackupDatabaseSuffix(); + _D("\"%s\" to \"%s\"", dbPath.c_str(), backupDbPath.c_str()); + if (0 != std::rename(backupDbPath.c_str(), dbPath.c_str())) { + _W("Fail to rollback"); + } + } +} + +#ifdef DBOX_ENABLED +void TaskDatabase::StepLiveboxDBInsert() +{ + if (m_context.widgetConfig.configInfo.m_livebox.size() <= 0) { + return; + } + + std::string tizenId = DPL::ToUTF8String(m_context.widgetConfig.tzAppid); + + // insert specific information to web livebox db + for (auto it = m_context.widgetConfig.configInfo.m_livebox.begin(); + it != m_context.widgetConfig.configInfo.m_livebox.end(); ++it) + { + std::string boxId = DPL::ToUTF8String((**it).m_liveboxId); + std::string boxType; + if ((**it).m_type.empty()) { + boxType = web_provider_livebox_get_default_type(); + } else { + boxType = DPL::ToUTF8String((**it).m_type); + } + _D("livebox id: %s", boxId.c_str()); + _D("livebox type: %s", boxType.c_str()); + + int autoLaunch = (**it).m_autoLaunch == L"true" ? 1 : 0; + _D("livebox auto-launch: %d", autoLaunch); + + int mouseEvent = (**it).m_boxInfo.m_boxMouseEvent == L"true" ? 1 : 0; + _D("livebox mouse-event: %d", mouseEvent); + + int pdFastOpen = (**it).m_boxInfo.m_pdFastOpen == L"true" ? 1 : 0; + _D("livebox pd fast-open: %d", pdFastOpen); + + if (m_context.isUpdateMode) { + web_provider_livebox_delete_by_app_id(tizenId.c_str()); + } + web_provider_livebox_insert_box_info( + boxId.c_str(), tizenId.c_str(), boxType.c_str(), + autoLaunch, mouseEvent, pdFastOpen); + } +} +#endif + +void TaskDatabase::StartStep() +{ + LOGD("--------- : START ----------"); +} + +void TaskDatabase::EndStep() +{ + LOGD("--------- : END ----------"); +} +} //namespace WidgetInstall +} //namespace Jobs diff --git a/src_wearable/jobs/widget_install/task_database.h b/src_wearable/jobs/widget_install/task_database.h new file mode 100755 index 0000000..9236b1b --- /dev/null +++ b/src_wearable/jobs/widget_install/task_database.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file task_database.h + * @author Lukasz Wrzosek(l.wrzosek@samsung.com) + * @author Soyoung kim(sy037.kim@samsung.com) + * @version 1.0 + * @brief Header file for installer task database updating + */ +#ifndef INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_DATABASE_H +#define INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_DATABASE_H + +#include +#include + +#include + +class InstallerContext; + +namespace Jobs { +namespace WidgetInstall { +class TaskDatabase : + public DPL::TaskDecl +{ + private: + InstallerContext& m_context; + WrtDB::ExternalLocationList m_externalLocationsToRemove; + + //TODO: temporary needed until security-server start to use pkgName instead + //of widget handle + std::list m_handleToRemoveList; + std::list m_handleList; + std::list m_backAppIdList; + WrtDB::TizenAppId m_orginAppId; + + void StepRegisterExternalFiles(); + void StepWrtDBInsert(); + void StepAceDBInsert(); + void StepSecurityOriginDBInsert(); + void StepWidgetInterfaceDBInsert(); + void StepRemoveExternalFiles(); + void StepLiveboxDBInsert(); + + void StepAbortDBInsert(); + void StepAbortAceDBInsert(); + void StepAbortWidgetInterfaceDBInsert(); + + void StartStep(); + void EndStep(); + + public: + TaskDatabase(InstallerContext& context); +}; +} //namespace WidgetInstall +} //namespace Jobs + +#endif // INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_DATABASE_H diff --git a/src_wearable/jobs/widget_install/task_encrypt_resource.cpp b/src_wearable/jobs/widget_install/task_encrypt_resource.cpp new file mode 100644 index 0000000..f048904 --- /dev/null +++ b/src_wearable/jobs/widget_install/task_encrypt_resource.cpp @@ -0,0 +1,347 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file task_ecnrypt_resource.cpp + * @author Soyoung Kim (sy037.kim@samsung.com) + * @version 1.0 + * @brief Implementation file for installer task encrypt resource + */ +#include "task_encrypt_resource.h" + +#undef __USE_FILE_OFFSET64 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +using namespace WrtDB; + +namespace { +const std::size_t ENCRYPTION_CHUNK_MAX_SIZE = 8192; // bytes +const std::size_t ENCRYPTION_DEC_CHUNK_SIZE = 4; // bytes + +std::set& getSupportedForEncryption() +{ + static std::set encryptSet; + if (encryptSet.empty()) { + encryptSet.insert(".html"); + encryptSet.insert(".htm"); + encryptSet.insert(".css"); + encryptSet.insert(".js"); + } + return encryptSet; +} + +bool isSupportedForEncryption(const std::string &file) +{ + size_t foundKey = file.rfind("."); + if (std::string::npos != foundKey) { + std::string mimeType = file.substr(foundKey); + std::transform(mimeType.begin(), mimeType.end(), mimeType.begin(), + ::tolower); + + return getSupportedForEncryption().count(mimeType) > 0; + } + return false; +} + +/** + * Opens a file. + * + * @param path Path to a file. + * @param mode Mode. + * @return Stream handle. + * @throw ExtractFileFailed If error (other than EINTR) occurs. + */ +FILE* openFile(const std::string& path, const std::string& mode) +{ + FILE* result = NULL; + + do + { + result = fopen(path.c_str(), mode.c_str()); + } while ((NULL == result) && (EINTR == errno)); + + if (NULL == result) + { + ThrowMsg(Jobs::WidgetInstall::Exceptions::EncryptionFailed, + "Could not open file " << path); + } + + return result; +} + +/** + * Reads bytes from a stream. + * + * @param buffer Buffer to read the bytes into. + * @param count Number of bytes to read. + * @param stream Stream to read from. + * @return Number of bytes read + * @throw ExtractFileFailed If error (other than EINTR) occurs. + */ +std::size_t readBytes(unsigned char* buffer, std::size_t count, FILE* stream) +{ + std::size_t result = std::fread(buffer, + sizeof(unsigned char), + count, + stream); + + if (result != count) + { + int error = errno; + if (0 != std::ferror(stream)) + { + if (EINTR != error) + { + ThrowMsg(Jobs::WidgetInstall::Exceptions::ErrorExternalInstallingFailure, + "Error while reading data" << + " [" << DPL::GetErrnoString(error) << "]"); + } + } + } + + return result; +} + +/** + * Writes bytes to a stream. + * + * @param buffer Data to write. + * @param count Number of bytes. + * @param stream Stream to write to. + * @throw ExtractFileFailed If error (other than EINTR) occurs. + */ +void writeBytes(unsigned char* buffer, std::size_t count, FILE* stream) +{ + std::size_t bytesWritten = 0; + std::size_t bytesToWrite = 0; + do + { + bytesToWrite = count - bytesWritten; + bytesWritten = std::fwrite(buffer + bytesWritten, + sizeof(unsigned char), + count - bytesWritten, + stream); + if ((bytesWritten != bytesToWrite) && (EINTR != errno)) + { + int error = errno; + ThrowMsg(Jobs::WidgetInstall::Exceptions::EncryptionFailed, + "Error while writing data" << + " [" << DPL::GetErrnoString(error) << "]"); + } + } while ((bytesWritten != bytesToWrite) && (EINTR == errno)); +} + +int ssmEncrypt(InstallMode::InstallTime time, std::string pkgId, const char* + inChunk, int inBytes, char** outChunk, int *outBytes) +{ + if (time == InstallMode::InstallTime::PRELOAD) { + return ssm_encrypt_preloaded_application(inChunk, inBytes, outChunk, outBytes); + } else { + return ssm_encrypt(pkgId.c_str(),pkgId.length(), inChunk, inBytes, outChunk, outBytes); + } +} + +} + +namespace Jobs { +namespace WidgetInstall { +TaskEncryptResource::TaskEncryptResource(InstallerContext& context) : + DPL::TaskDecl(this), + m_context(context) +{ + AddStep(&TaskEncryptResource::StartStep); + AddStep(&TaskEncryptResource::StepEncryptResource); + AddStep(&TaskEncryptResource::EndStep); +} + +void TaskEncryptResource::StepEncryptResource() +{ + _D("Step Encrypt resource"); + + EncryptDirectory(m_context.locations->getSourceDir()); +} + +void TaskEncryptResource::EncryptDirectory(std::string path) +{ + FTS *fts; + FTSENT *ftsent; + char * const paths[] = { const_cast(path.c_str()), NULL }; + + if ((fts = fts_open(paths, FTS_PHYSICAL | FTS_NOCHDIR, NULL)) == NULL) { + //ERROR + int error = errno; + _W("%s: fts_open failed with error: %s", __PRETTY_FUNCTION__, strerror(error)); + ThrowMsg(Exceptions::EncryptionFailed, "Error reading directory: " + << path); + } + + while ((ftsent = fts_read(fts)) != NULL) { + switch (ftsent->fts_info) { + case FTS_DP: + case FTS_DC: + case FTS_D: + case FTS_DEFAULT: + case FTS_SLNONE: + //directories, non-regular files, dangling symbolic links + break; + case FTS_F: + case FTS_NSOK: + case FTS_SL: + //regular files and other objects that can be counted + if (isSupportedForEncryption(ftsent->fts_path)) { + EncryptFile(ftsent->fts_path); + } + break; + case FTS_NS: + case FTS_DOT: + case FTS_DNR: + case FTS_ERR: + default: + _W("%s: traversal failed on file: %s with error: %s", __PRETTY_FUNCTION__, ftsent->fts_path, strerror(ftsent->fts_errno)); + ThrowMsg(Exceptions::EncryptionFailed, "Error reading file"); + break; + } + } + + if (fts_close(fts) == -1) { + int error = errno; + _W("%s: fts_close failed with error: %s", __PRETTY_FUNCTION__, strerror(error)); + } +} + +void TaskEncryptResource::EncryptFile(const std::string &fileName) +{ + _D("Encrypt file: %s", fileName.c_str()); + std::string encFile = fileName + ".enc"; + + struct stat info; + memset(&info, 0, sizeof(info)); + if (stat(fileName.c_str(), &info) != 0) + { + int error = errno; + ThrowMsg(Exceptions::EncryptionFailed, + "Could not access file " << fileName << + "[" << DPL::GetErrnoString(error) << "]"); + } + const std::size_t fileSize = info.st_size; + if (0 == fileSize) { + _D("%s size is 0, so encryption is skiped", fileName.c_str()); + return; + } + + // If update installed preload web, should skip encryption. + if (!(m_context.mode.rootPath == InstallMode::RootPath::RO && + (m_context.mode.installTime == InstallMode::InstallTime::PRELOAD + || m_context.mode.installTime == InstallMode::InstallTime::FOTA) + && m_context.mode.extension == InstallMode::ExtensionType::DIR)) { + + DPL::ScopedFClose inFile(openFile(fileName, "r")); + DPL::ScopedFClose outFile(openFile(encFile, "w")); + + const std::size_t chunkSize = (fileSize > ENCRYPTION_CHUNK_MAX_SIZE + ? ENCRYPTION_CHUNK_MAX_SIZE : fileSize); + + std::unique_ptr inChunk(new unsigned char[chunkSize]); + std::size_t bytesRead = 0; + std::string pkgId = DPL::ToUTF8String(m_context.widgetConfig.tzPkgid); + + do + { + bytesRead = readBytes(inChunk.get(), chunkSize, inFile.Get()); + if (0 != bytesRead) { + int outDecSize = 0; + char *outChunk = NULL; + if (0 != ssmEncrypt(m_context.mode.installTime, pkgId, + (char*)inChunk.get(), (int)bytesRead, + &outChunk, &outDecSize)) { + ThrowMsg(Exceptions::EncryptionFailed, + "Encryption Failed using TrustZone"); + } + + std::stringstream toString; + toString << outDecSize; + + writeBytes((unsigned char*)toString.str().c_str(), + sizeof(int), outFile.Get()); + writeBytes((unsigned char*)outChunk, outDecSize, outFile.Get()); + delete outChunk; + } + inChunk.reset(new unsigned char[chunkSize]); + + } while (0 == std::feof(inFile.Get())); + + outFile.Reset(); + inFile.Reset(); + + _D("File encrypted successfully"); + _D("Remove plain-text file: %s", fileName.c_str()); + if (0 != unlink(fileName.c_str())) + { + Throw(Exceptions::EncryptionFailed); + } + + _D("Rename encrypted file"); + if (0 != std::rename(encFile.c_str(), fileName.c_str())) + { + Throw(Exceptions::EncryptionFailed); + } + } + + WrtDB::EncryptedFileInfo fileInfo; + fileInfo.fileName = DPL::FromUTF8String(fileName); + fileInfo.fileSize = fileSize; + + m_context.widgetConfig.encryptedFiles.insert(fileInfo); +} + +void TaskEncryptResource::StartStep() +{ + LOGD("--------- : START ----------"); +} + +void TaskEncryptResource::EndStep() +{ + m_context.job->UpdateProgress( + InstallerContext::INSTALL_ECRYPTION_FILES, + "Ecrypt resource files"); + + LOGD("--------- : END ----------"); +} +} //namespace WidgetInstall +} //namespace Jobs diff --git a/src_wearable/jobs/widget_install/task_encrypt_resource.h b/src_wearable/jobs/widget_install/task_encrypt_resource.h new file mode 100644 index 0000000..b89a992 --- /dev/null +++ b/src_wearable/jobs/widget_install/task_encrypt_resource.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file task_encrypt_resource.h + * @author soyoung kim (sy037.kim@samsung.com) + * @version 1.0 + */ + +#ifndef SRC_JOBS_WIDGET_INSTALL_TASK_RESOURCE_ENCRYPT_H_ +#define SRC_JOBS_WIDGET_INSTALL_TASK_RESOURCE_ENCRYPT_H_ + +#include +#include + +class InstallerContext; + +namespace Jobs { +namespace WidgetInstall { +class TaskEncryptResource : public DPL::TaskDecl +{ + private: + // Installation context + InstallerContext &m_context; + std::string tempInstalledPath; + + void StepEncryptResource(); + + void StartStep(); + void EndStep(); + + void EncryptDirectory(std::string path); + void EncryptFile(const std::string &fileName); + + public: + explicit TaskEncryptResource(InstallerContext &installerContext); +}; +} // namespace WidgetInstall +} // namespace Jobs +#endif /* SRC_JOBS_WIDGET_INSTALL_TASK_ENCRYPT_RESOURCE_H_ */ diff --git a/src_wearable/jobs/widget_install/task_file_manipulation.cpp b/src_wearable/jobs/widget_install/task_file_manipulation.cpp new file mode 100644 index 0000000..ae1128e --- /dev/null +++ b/src_wearable/jobs/widget_install/task_file_manipulation.cpp @@ -0,0 +1,326 @@ +/* + * Copyright (c) 2010 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file task_db_update.cpp + * @author Lukasz Wrzosek(l.wrzosek@samsung.com) + * @version 1.0 + * @brief Implementation file for installer task database updating + */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define WEBAPP_DEFAULT_UID 5000 +#define WEBAPP_DEFAULT_GID 5000 + +namespace { +const mode_t PRIVATE_STORAGE_MODE = 0700; +const mode_t SHARED_STORAGE_MODE = 0755; +} + +using namespace WrtDB; + +namespace { +const char* GLIST_RES_DIR = "res"; + +bool _FolderCopy(std::string source, std::string dest) +{ + DIR* dir = opendir(source.c_str()); + if (NULL == dir) { + return false; + } + + struct dirent dEntry; + struct dirent *dEntryResult; + int return_code; + + do { + struct stat statInfo; + return_code = readdir_r(dir, &dEntry, &dEntryResult); + if (dEntryResult != NULL && return_code == 0) { + std::string fileName = dEntry.d_name; + std::string fullName = source + "/" + fileName; + + if (stat(fullName.c_str(), &statInfo) != 0) { + closedir(dir); + return false; + } + + if (S_ISDIR(statInfo.st_mode)) { + if (("." == fileName) || (".." == fileName)) { + continue; + } + std::string destFolder = dest + "/" + fileName; + WrtUtilMakeDir(destFolder); + + if (!_FolderCopy(fullName, destFolder)) { + closedir(dir); + return false; + } + } + + std::string destFile = dest + "/" + fileName; + std::ifstream infile(fullName); + std::ofstream outfile(destFile); + outfile << infile.rdbuf(); + outfile.close(); + infile.close(); + } + } while (dEntryResult != NULL && return_code == 0); + closedir(dir); + return true; +} +} + +namespace Jobs { +namespace WidgetInstall { +TaskFileManipulation::TaskFileManipulation(InstallerContext& context) : + DPL::TaskDecl(this), + m_context(context), + m_extHandle(NULL) +{ + AddStep(&TaskFileManipulation::StartStep); + AddStep(&TaskFileManipulation::StepCheckInstallLocation); + AddStep(&TaskFileManipulation::StepPrepareRootDirectory); + if (m_context.mode.extension != InstallMode::ExtensionType::DIR) + { + AddStep(&TaskFileManipulation::StepUnzipWgtFile); + } + AddStep(&TaskFileManipulation::EndStep); + + AddAbortStep(&TaskFileManipulation::StepAbortPrepareRootDirectory); +} + +void TaskFileManipulation::StepCheckInstallLocation() +{ + _D("StepCheckInstallLocation"); + if (m_context.mode.rootPath == InstallMode::RootPath::RO) { + m_context.locationType = INSTALL_LOCATION_TYPE_INTERNAL_ONLY; + return; + } + + // If webapp is hybrid app, it should be installed to internal storage. + // Because Service app should be installed to internal. + if (m_context.widgetConfig.packagingType == PKG_TYPE_HYBRID_WEB_APP) { + m_context.locationType = INSTALL_LOCATION_TYPE_INTERNAL_ONLY; + return; + } + + std::string installedPath = WrtDB::GlobalConfig::GetUserInstalledWidgetPath(); + WidgetUnzip wgtUnzip(m_context.requestedPath); + + if (m_context.locationType == INSTALL_LOCATION_TYPE_AUTO) { + int storage = 0; + // vconf_get_int(VCONFKEY_SETAPPL_DEFAULT_MEM_INSTALL_APPLICATIONS_INT) + // 0 : phone internal memory + // 1 : SD card + if (vconf_get_int(VCONFKEY_SETAPPL_DEFAULT_MEM_INSTALL_APPLICATIONS_INT, + &storage)) { + _E("vconf_get_int(VCONFKEY_SETAPPL_DEFAULT_MEM_INSTALL_APPLICATIONS_INT) \ + failed."); + } + _D("default setting : storage [%d]", storage); + if (storage) { + m_context.locationType = INSTALL_LOCATION_TYPE_PREFER_EXTERNAL; + } else { + m_context.locationType = INSTALL_LOCATION_TYPE_INTERNAL_ONLY; + if(!wgtUnzip.checkAvailableSpace(installedPath)) { + m_context.locationType = INSTALL_LOCATION_TYPE_PREFER_EXTERNAL; + } + } + } + + if (m_context.locationType == INSTALL_LOCATION_TYPE_PREFER_EXTERNAL) { + int mmcStatus; + if (vconf_get_int(VCONFKEY_SYSMAN_MMC_STATUS, &mmcStatus)) { + _E("vconf_get_int(VCONFKEY_SYSMAN_MMC_STATUS) failed."); + mmcStatus = VCONFKEY_SYSMAN_MMC_INSERTED_NOT_MOUNTED; + } + + if (VCONFKEY_SYSMAN_MMC_MOUNTED != mmcStatus) { + _D("mmcStatus is MMC_REMOVED or NOT_MOUNTED."); + m_context.locationType = INSTALL_LOCATION_TYPE_INTERNAL_ONLY; + } + } + + if (m_context.locationType == INSTALL_LOCATION_TYPE_INTERNAL_ONLY) { + if(!wgtUnzip.checkAvailableSpace(installedPath)) { + ThrowMsg(Exceptions::OutOfStorageFailed, "There is no space for installation"); + } + } +} + +void TaskFileManipulation::StepPrepareRootDirectory() +{ + if (m_context.locationType == INSTALL_LOCATION_TYPE_PREFER_EXTERNAL) { + prepareExternalDir(); + } else { + std::string widgetPath = m_context.locations->getPackageInstallationDir(); + std::string widgetBinPath = m_context.locations->getBinaryDir(); + std::string widgetSrcPath = m_context.locations->getSourceDir(); + + if (!m_context.isUpdateMode) { + _D("Remove existing directory : %s", widgetPath.c_str()); + DPL::Utils::TryRemove(DPL::Utils::Path(widgetPath)); + } + WrtUtilMakeDir(widgetPath); + + _D("Create resource directory"); + WrtUtilMakeDir(widgetBinPath); + WrtUtilMakeDir(widgetSrcPath); + } + + m_context.job->UpdateProgress( + InstallerContext::INSTALL_DIR_CREATE, + "Widget Directory Created"); +} + +void TaskFileManipulation::StepUnzipWgtFile() +{ + if (m_context.widgetConfig.packagingType != PKG_TYPE_HOSTED_WEB_APP) { + std::string instDir; + if (m_context.widgetConfig.packagingType == PKG_TYPE_HYBRID_WEB_APP) { + instDir = m_context.locations->getPackageInstallationDir(); + } else { + instDir = m_context.locations->getSourceDir(); + } + + _D("unzip file to %s", instDir.c_str()); + + WidgetUnzip wgtUnzip(m_context.requestedPath); + wgtUnzip.unzipWgtFile(instDir); + } else { + _D("From browser installation - unzip is not done"); + } + + m_context.job->UpdateProgress( + InstallerContext::INSTALL_UNZIP_WGT, + "Unzip Wgt file"); +} + +void TaskFileManipulation::StepAbortPrepareRootDirectory() +{ + _D("[Create Root Directory] Aborting.... (Rename path)"); + if (m_context.locationType == INSTALL_LOCATION_TYPE_PREFER_EXTERNAL) { + if (m_context.isUpdateMode) { + WidgetInstallToExtSingleton::Instance().postUpgrade(false); + } else { + WidgetInstallToExtSingleton::Instance().postInstallation(false); + } + WidgetInstallToExtSingleton::Instance().deinitialize(); + } else { + std::string widgetPath; + widgetPath = m_context.locations->getPackageInstallationDir(); + if (!WrtUtilRemove(widgetPath)) { + _E("Error occurs during removing existing folder"); + } + // Remove user data directory if preload web app. + std::string userData = m_context.locations->getUserDataRootDir(); + if (0 == access(userData.c_str(), F_OK)) { + if (!WrtUtilRemove(userData)) { + _E("Error occurs during removing user data directory"); + } + } + } +} + +void TaskFileManipulation::prepareExternalDir() +{ + _D("Step prepare to install in exernal directory"); + Try { + std::string pkgid = + DPL::ToUTF8String(m_context.widgetConfig.tzPkgid); + + WidgetInstallToExtSingleton::Instance().initialize(pkgid); + + std::unique_ptr zipFile(new + DPL::ZipInput(m_context.requestedPath)); + double unzipSize = zipFile->GetTotalUncompressedSize(); + int folderSize = (int)(unzipSize / (1024 * 1024)) + 1; + + GList *list = NULL; + app2ext_dir_details* dirDetail = NULL; + + dirDetail = (app2ext_dir_details*) calloc(1, + sizeof( + app2ext_dir_details)); + if (NULL == dirDetail) { + ThrowMsg(Exceptions::ErrorExternalInstallingFailure, + "error in app2ext"); + } + dirDetail->name = strdup(GLIST_RES_DIR); + dirDetail->type = APP2EXT_DIR_RO; + list = g_list_append(list, dirDetail); + + if (m_context.isUpdateMode) { + WidgetInstallToExtSingleton::Instance().preUpgrade(list, + folderSize); + } else { + WidgetInstallToExtSingleton::Instance().preInstallation(list, + folderSize); + } + free(dirDetail); + g_list_free(list); + + /* make bin directory */ + std::string widgetBinPath = m_context.locations->getBinaryDir(); + WrtUtilMakeDir(widgetBinPath); + std::string sourceDir = m_context.locations->getSourceDir(); + WrtUtilMakeDir(sourceDir); + } + Catch(DPL::ZipInput::Exception::OpenFailed) { + ReThrowMsg(Exceptions::ErrorExternalInstallingFailure, + "Error during \ + create external folder "); + } + Catch(WidgetInstallToExt::Exception::ErrorInstallToExt) + { + ReThrowMsg(Exceptions::ErrorExternalInstallingFailure, + "Error during create external folder "); + } +} + +void TaskFileManipulation::StartStep() +{ + LOGD("--------- : START ----------"); +} + +void TaskFileManipulation::EndStep() +{ + LOGD("--------- : END ----------"); +} +} //namespace WidgetInstall +} //namespace Jobs diff --git a/src_wearable/jobs/widget_install/task_file_manipulation.h b/src_wearable/jobs/widget_install/task_file_manipulation.h new file mode 100644 index 0000000..113ca72 --- /dev/null +++ b/src_wearable/jobs/widget_install/task_file_manipulation.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file task_db_update.h + * @author Lukasz Wrzosek(l.wrzosek@samsung.com) + * @version 1.0 + * @brief Header file for installer task database updating + */ +#ifndef INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_FILE_MANIPULATION_H +#define INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_FILE_MANIPULATION_UPDATE_H + +#include +#include + +class InstallerContext; + +namespace Jobs { +namespace WidgetInstall { +class TaskFileManipulation : + public DPL::TaskDecl +{ + InstallerContext& m_context; + app2ext_handle *m_extHandle; + + // install internal location + void StepCheckInstallLocation(); + void StepPrepareRootDirectory(); + void StepUnzipWgtFile(); + void StepAbortPrepareRootDirectory(); + void StepLinkForPreload(); + void StartStep(); + void EndStep(); + + // install external location + void prepareExternalDir(); + + public: + TaskFileManipulation(InstallerContext& context); +}; +} //namespace WidgetInstall +} //namespace Jobs + +#endif // INSTALLER_CORE_JOS_WIDGET_INSTALL_FILE_MANIPULATION_H diff --git a/src_wearable/jobs/widget_install/task_install_ospsvc.cpp b/src_wearable/jobs/widget_install/task_install_ospsvc.cpp new file mode 100644 index 0000000..4016a6f --- /dev/null +++ b/src_wearable/jobs/widget_install/task_install_ospsvc.cpp @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file task_install_ospsvc.cpp + * @author Soyoung Kim (sy037.kim@samsung.com) + * @version 1.0 + * @brief Implementation file for installer task install osp service + */ +#include "task_install_ospsvc.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +using namespace WrtDB; + +namespace { +const int MAX_BUF_SIZE = 128; +const char* OSP_INSTALL_STR1 = "/usr/etc/package-manager/backend/tpk -iv "; +const char* OSP_INSTALL_STR2 = " -p "; +} + +namespace Jobs { +namespace WidgetInstall { +TaskInstallOspsvc::TaskInstallOspsvc(InstallerContext& context) : + DPL::TaskDecl(this), + m_context(context) +{ + AddStep(&TaskInstallOspsvc::StartStep); + AddStep(&TaskInstallOspsvc::StepUninstallSmack); + AddStep(&TaskInstallOspsvc::StepInstallOspService); + AddStep(&TaskInstallOspsvc::EndStep); +} + +void TaskInstallOspsvc::StepUninstallSmack() +{ + std::string pkgId = DPL::ToUTF8String(m_context.widgetConfig.tzPkgid); + if (m_context.isUpdateMode) { + _D("StepUninstallSmack"); + if (PC_OPERATION_SUCCESS != perm_app_uninstall(pkgId.c_str())) { + _E("failure in removing smack rules file"); + ThrowMsg(Exceptions::NotAllowed, "Update failure. " + "failure in delete smack rules file before update."); + } + } +} + +void TaskInstallOspsvc::StepInstallOspService() +{ + _D("Step: installation for osp service"); + + std::ostringstream commStr; + commStr << OSP_INSTALL_STR1<< BashUtils::escape_arg( + m_context.locations->getPackageInstallationDir()) + << OSP_INSTALL_STR2 << m_context.certLevel; + _D("osp install command : %s", commStr.str().c_str()); + + char readBuf[MAX_BUF_SIZE]; + FILE *fd; + fd = popen(commStr.str().c_str(), "r"); + if (NULL == fd) { + _E("Failed to installtion osp service"); + ThrowMsg(Exceptions::InstallOspsvcFailed, + "Error occurs during\ + install osp service"); + } + + if (fgets(readBuf, MAX_BUF_SIZE, fd) == NULL) + { + _E("Failed to installtion osp service.\ + Inability of reading file."); + ThrowMsg(Exceptions::InstallOspsvcFailed, + "Error occurs during\ + install osp service"); + } + _D("return value : %s", readBuf); + + int result = atoi(readBuf); + if (0 != result) { + ThrowMsg(Exceptions::InstallOspsvcFailed, + "Error occurs during\ + install osp service"); + } + + pclose(fd); +} + +void TaskInstallOspsvc::StartStep() +{ + LOGD("--------- : START ----------"); +} + +void TaskInstallOspsvc::EndStep() +{ + m_context.job->UpdateProgress( + InstallerContext::INSTALL_INSTALL_OSPSVC, + "Installed Osp servcie"); + + LOGD("--------- : END ----------"); +} +} //namespace WidgetInstall +} //namespace Jobs diff --git a/src_wearable/jobs/widget_install/task_install_ospsvc.h b/src_wearable/jobs/widget_install/task_install_ospsvc.h new file mode 100644 index 0000000..6648d73 --- /dev/null +++ b/src_wearable/jobs/widget_install/task_install_ospsvc.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file task_install_ospsvc.h + * @author soyoung kim (sy037.kim@samsung.com) + * @version 1.0 + */ + +#ifndef SRC_JOBS_WIDGET_INSTALL_TASK_INSTALL_OSPSVC_H_ +#define SRC_JOBS_WIDGET_INSTALL_TASK_INSTALL_OSPSVC_H_ + +#include +#include + +class InstallerContext; + +namespace Jobs { +namespace WidgetInstall { +class TaskInstallOspsvc : public DPL::TaskDecl +{ + private: + // Installation context + InstallerContext &m_context; + + void StepInstallOspService(); + void StepUninstallSmack(); + + void StepAbortInstall(); + + void StartStep(); + void EndStep(); + + // return callback + static int StatusCallback( + int req_id, const char *pkg_type, const char *pkg_name, + const char *key, const char *val, const void *pmsg, + void *priv_data); + + public: + explicit TaskInstallOspsvc(InstallerContext &installerContext); +}; +} // namespace WidgetInstall +} // namespace Jobs +#endif /* SRC_JOBS_WIDGET_INSTALL_TASK_INSTALL_OSPSVC_H_ */ diff --git a/src_wearable/jobs/widget_install/task_manifest_file.cpp b/src_wearable/jobs/widget_install/task_manifest_file.cpp new file mode 100755 index 0000000..ac897fa --- /dev/null +++ b/src_wearable/jobs/widget_install/task_manifest_file.cpp @@ -0,0 +1,1614 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file task_manifest_file.cpp + * @author Pawel Sikorski (p.sikorski@samgsung.com) + * @version + * @brief + */ + +//SYSTEM INCLUDES +#include +#include +#include +#include +#include +#include + +//WRT INCLUDES +#include +#include +#include +#include +#ifdef DBOX_ENABLED +#include +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define DEFAULT_ICON_NAME "icon.png" +#define DEFAULT_PREVIEW_NAME "preview.png" + +using namespace WrtDB; + +namespace { +typedef std::map LanguageTagMap; + +const char* const STR_TRUE = "true"; +const char* const STR_FALSE = "false"; +const char* const STR_NODISPLAY = "nodisplay"; +const char* const STR_CATEGORY_WATCH_CLOCK = "com.samsung.wmanager.WATCH_CLOCK"; +const char* const STR_CATEGORY_WATCH_APP = "com.samsung.wmanager.WATCH_APP"; + +#ifdef IME_ENABLED +const char* const STR_CATEGORY_IME = "http://tizen.org/category/ime"; +#endif + +#ifdef SERVICE_ENABLED +const char* const STR_CATEGORY_SERVICE = "http://tizen.org/category/service"; +#endif + +LanguageTagMap getLanguageTagMap() +{ + LanguageTagMap map; + +#define ADD(tag, l_tag) map.insert(std::make_pair(L###tag, L###l_tag)); +#include "languages.def" +#undef ADD + + return map; +} + +DPL::OptionalString getLangTag(const DPL::String& tag) +{ + static LanguageTagMap TagsMap = + getLanguageTagMap(); + + DPL::String langTag = tag; + + _D("Trying to map language tag: %ls", langTag.c_str()); + size_t pos = langTag.find_first_of(L'_'); + if (pos != DPL::String::npos) { + langTag.erase(pos); + } + DPL::OptionalString ret; + + LanguageTagMap::iterator it = TagsMap.find(langTag); + if (it != TagsMap.end()) { + ret = it->second; + _D("Mapping IANA Language tag to language tag: %ls -> %ls", langTag.c_str(), (*ret).c_str()); + } + + return ret; +} +} + +namespace Jobs { +namespace WidgetInstall { +const char * TaskManifestFile::encoding = "UTF-8"; + +TaskManifestFile::TaskManifestFile(InstallerContext &inCont) : + DPL::TaskDecl(this), + m_context(inCont), + writer(NULL) +{ + if (InstallMode::Command::RECOVERY == m_context.mode.command) { + AddStep(&TaskManifestFile::stepGenerateManifest); + } else { + AddStep(&TaskManifestFile::stepCopyIconFiles); +#ifdef DBOX_ENABLED + AddStep(&TaskManifestFile::stepCopyLiveboxFiles); +#endif +#ifdef SERVICE_ENABLED + AddStep(&TaskManifestFile::stepCopyServiceIconFiles); +#endif + AddStep(&TaskManifestFile::stepCopyAccountIconFiles); + AddStep(&TaskManifestFile::stepCreateExecFile); + AddStep(&TaskManifestFile::stepCreateLinkNPPluginsFile); + AddStep(&TaskManifestFile::stepGenerateManifest); + } +} + +TaskManifestFile::~TaskManifestFile() +{} + +void TaskManifestFile::stepCreateExecFile() +{ + std::string exec = m_context.locations->getExecFile(); + std::string clientExeStr = GlobalConfig::GetWrtClientExec(); + +#ifdef MULTIPROCESS_SERVICE_SUPPORT + //default widget + std::stringstream postfix; + postfix << AppControlPrefix::PROCESS_PREFIX << 0; + std::string controlExec = exec; + controlExec.append(postfix.str()); + + errno = 0; + if (symlink(clientExeStr.c_str(), controlExec.c_str()) != 0) + { + int error = errno; + if (error) + _E("Failed to make a symbolic name for a file [%s]", DPL::GetErrnoString(error).c_str()); + } + + // app-control widgets + unsigned int indexMax = 0; + FOREACH(it, m_context.widgetConfig.configInfo.appControlList) { + if (it->m_index > indexMax) { + indexMax = it->m_index; + } + } + + for (std::size_t i = 1; i <= indexMax; ++i) { + std::stringstream postfix; + postfix << AppControlPrefix::PROCESS_PREFIX << i; + std::string controlExec = exec; + controlExec.append(postfix.str()); + errno = 0; + if (symlink(clientExeStr.c_str(), controlExec.c_str()) != 0) { + int error = errno; + if (error) { + _E("Failed to make a symbolic name for a file [%s]", DPL::GetErrnoString(error).c_str()); + } + } + } +#else + //default widget + _D("link -s %s %s", clientExeStr.c_str(), exec.c_str()); + errno = 0; + if (symlink(clientExeStr.c_str(), exec.c_str()) != 0) + { + int error = errno; + if (error) + _E("Failed to make a symbolic name for a file [%s]", DPL::GetErrnoString(error).c_str()); + } +#ifdef SERVICE_ENABLED + std::string serviceExeStr = GlobalConfig::GetWrtServiceExec(); + + FOREACH(it, m_context.widgetConfig.configInfo.serviceAppInfoList) { + std::string serviceExec = m_context.locations->getBinaryDir() + "/" + DPL::ToUTF8String(it->serviceId); + errno = 0; + _D("link -s %s %s", serviceExeStr.c_str(), serviceExec.c_str()); + if (symlink(serviceExeStr.c_str(), serviceExec.c_str()) != 0) + { + int error = errno; + if (error) + _E("Failed to make a symbolic name for a file [%s]", DPL::GetErrnoString(error).c_str()); + } + } +#endif +#endif + // creation of box symlink + ConfigParserData::LiveboxList& liveboxList = + m_context.widgetConfig.configInfo.m_livebox; + if (!liveboxList.empty()) { + std::string boxExec = "/usr/bin/WebProcess"; + std::string boxSymlink = m_context.locations->getExecFile(); + boxSymlink += ".d-box"; + + errno = 0; + if (symlink(boxExec.c_str(), boxSymlink.c_str()) != 0) { + int error = errno; + if (error) { + _E("Failed to make a symbolic name for a file [%s]", DPL::GetErrnoString(error).c_str()); + } + } + } + + m_context.job->UpdateProgress( + InstallerContext::INSTALL_CREATE_EXECFILE, + "Widget execfile creation Finished"); +} + +void TaskManifestFile::stepCreateLinkNPPluginsFile() +{ + _D("stepCreateLinkNPPluginsFile"); + if (0 == access(m_context.locations->getNPPluginsDir().c_str(), F_OK)) { + _D("This webapp has NPPlugins"); + std::string pluginsExec = "/usr/bin/PluginProcess"; + errno = 0; + if (symlink(pluginsExec.c_str(), + m_context.locations->getNPPluginsExecFile().c_str()) != 0) { + int error = errno; + if (error) { + _E("Failed to create symbolic link for npplugins : %ls", + DPL::GetErrnoString(error).c_str()); + } + } + } +} + +void TaskManifestFile::stepCopyIconFiles() +{ + _D("CopyIconFiles"); + + //This function copies icon to desktop icon path. For each locale avaliable + //which there is at least one icon in widget for, icon file is copied. + //Coping prioritize last positions when coping. If there is several icons + //with given locale, the one, that will be copied, will be icon + //which is declared by tag later than the others in config.xml of + // widget + + std::vector generatedLocales; + + WrtDB::WidgetRegisterInfo::LocalizedIconList & icons = + m_context.widgetConfig.localizationData.icons; + + for (WrtDB::WidgetRegisterInfo::LocalizedIconList::const_iterator + icon = icons.begin(); + icon != icons.end(); + ++icon) + { + DPL::String src = icon->src; + FOREACH(locale, icon->availableLocales) + { + DPL::String tmp = (icon->isSmall ? L"small_" : L"") + (*locale); + _D("Icon for locale: %ls is: %ls", tmp.c_str(), src.c_str()); + + if (std::find(generatedLocales.begin(), generatedLocales.end(), + tmp) != generatedLocales.end()) + { + _D("Skipping - has that locale"); + continue; + } else { + generatedLocales.push_back(tmp); + } + + DPL::Utils::Path sourceFile(m_context.locations->getSourceDir()); + if (!locale->empty()) { + sourceFile /= "locales"; + sourceFile /= *locale; + } + sourceFile /= src; + + DPL::Utils::Path + targetFile(m_context.locations->getSharedResourceDir()); + targetFile /= (icon->isSmall ? L"small_" : L"") + + getIconTargetFilename(*locale, sourceFile.Extension()); + + if (m_context.widgetConfig.packagingType == + WrtDB::PKG_TYPE_HOSTED_WEB_APP) + { + m_context.locations->setIconTargetFilenameForLocale( + targetFile.Fullpath()); + } + + _D("Copying icon: %s -> %s", sourceFile.Filename().c_str(), targetFile.Filename().c_str()); + + icon_list.push_back(targetFile.Fullpath()); + + Try + { + DPL::FileInput input(sourceFile.Fullpath()); + DPL::FileOutput output(targetFile.Fullpath()); + DPL::Copy(&input, &output); + } + + Catch(DPL::FileInput::Exception::Base) + { + // Error while opening or closing source file + //ReThrowMsg(InstallerException::CopyIconFailed, + // sourceFile.str()); + _E("Copying widget's icon failed. Widget's icon will not be" \ + "available from Main Screen"); + } + + Catch(DPL::FileOutput::Exception::Base) + { + // Error while opening or closing target file + //ReThrowMsg(InstallerException::CopyIconFailed, + // targetFile.str()); + _E("Copying widget's icon failed. Widget's icon will not be" \ + "available from Main Screen"); + } + + Catch(DPL::CopyFailed) + { + // Error while copying + //ReThrowMsg(InstallerException::CopyIconFailed, + // targetFile.str()); + _E("Copying widget's icon failed. Widget's icon will not be" \ + "available from Main Screen"); + } + } + } + + m_context.job->UpdateProgress( + InstallerContext::INSTALL_COPY_ICONFILE, + "Widget iconfile copy Finished"); +} + +#ifdef SERVICE_ENABLED +void TaskManifestFile::stepCopyServiceIconFiles() +{ + _D("Copy Service icon files"); + + WrtDB::ConfigParserData::ServiceAppInfoList service = m_context.widgetConfig.configInfo.serviceAppInfoList; + + if (service.size() <= 0) { + return; + } + + FOREACH(it, service) + { + if (it->m_iconsList.empty()) { + _D("Widget doesn't contain Service icon"); + return; + } + + ConfigParserData::IconsList iconsList = it->m_iconsList; + FOREACH(iconIt, iconsList) { + std::string sourceFile = m_context.locations->getSourceDir() + + '/' + + DPL::ToUTF8String(iconIt->src); + std::string targetFile = m_context.locations->getSharedResourceDir() + + '/' + + DPL::ToUTF8String(it->serviceId) + + ".png"; + copyFile(sourceFile, targetFile); + } + } +} +#endif + +#ifdef DBOX_ENABLED +void TaskManifestFile::stepCopyLiveboxFiles() +{ + _D("Copy Livebox Files"); + + using namespace WrtDB; + ConfigParserData &data = m_context.widgetConfig.configInfo; + ConfigParserData::LiveboxList liveBoxList = data.m_livebox; + + if (liveBoxList.size() <= 0) { + return; + } + + std::ostringstream sourceFile; + std::ostringstream targetFile; + + FOREACH (boxIt, liveBoxList) { + ConfigParserData::LiveboxInfo::BoxSizeList boxSizeList = + (**boxIt).m_boxInfo.m_boxSize; + FOREACH (sizeIt, boxSizeList) { + std::string preview = DPL::ToUTF8String((*sizeIt).m_preview); + if (preview.empty()) { + continue; + } + sourceFile << m_context.locations->getSourceDir() << "/"; + sourceFile << preview; + targetFile << m_context.locations->getSharedDataDir() << "/"; + targetFile << (**boxIt).m_liveboxId << "."; + targetFile << DPL::ToUTF8String((*sizeIt).m_size) << "." << DEFAULT_PREVIEW_NAME; + + copyFile(sourceFile.str(), targetFile.str()); + + // clear stream objects + sourceFile.str(""); + targetFile.str(""); + } + // check this livebox has icon element + std::string icon = DPL::ToUTF8String((**boxIt).m_icon); + if (icon.empty()) { + continue; + } + sourceFile << m_context.locations->getSourceDir() << "/"; + sourceFile << icon; + targetFile << m_context.locations->getSharedDataDir() << "/"; + targetFile << (**boxIt).m_liveboxId << "." << DEFAULT_ICON_NAME; + + copyFile(sourceFile.str(), targetFile.str()); + + // clear stream objects + sourceFile.str(""); + targetFile.str(""); + } + m_context.job->UpdateProgress( + InstallerContext::INSTALL_COPY_LIVEBOX_FILES, + "Livebox files copy Finished"); +} +#endif + +void TaskManifestFile::stepCopyAccountIconFiles() +{ + _D("Copy Account icon files"); + WrtDB::ConfigParserData::AccountProvider account = + m_context.widgetConfig.configInfo.accountProvider; + + if (account.m_iconSet.empty()) { + _D("Widget doesn't contain Account"); + return; + } + + FOREACH(it, account.m_iconSet) { + std::string sourceFile = m_context.locations->getSourceDir() + + '/' + + DPL::ToUTF8String(it->second); + std::string targetFile = m_context.locations->getSharedResourceDir() + + '/' + + DPL::ToUTF8String(it->second); + copyFile(sourceFile, targetFile); + } +} + +void TaskManifestFile::copyFile(const std::string& sourceFile, + const std::string& targetFile) +{ + Try + { + DPL::FileInput input(sourceFile); + DPL::FileOutput output(targetFile); + DPL::Copy(&input, &output); + } + Catch(DPL::Exception) + { + _E("Failed to file copy. %s to %s", sourceFile.c_str(), targetFile.c_str()); + ReThrowMsg(Exceptions::CopyIconFailed, "Error during file copy."); + } +} + +#ifdef DBOX_ENABLED +bool TaskManifestFile::addBoxUiApplication(Manifest& manifest) +{ + UiApplication uiApp; + std::string postfix = ".d-box"; + static bool isAdded = false; + + Try + { + if (isAdded) { + _D("UiApplication for d-box is already added"); + return false; + } + uiApp.setNodisplay(true); + uiApp.setTaskmanage(false); + uiApp.setMultiple(false); + setWidgetName(manifest, uiApp); + setWidgetIcons(uiApp); + + // appid for box is like [webapp id].d-box + setWidgetIds(manifest, uiApp, postfix); + // executable path for box is like [app path]/bin/[webapp id].d-box + setWidgetExecPath(uiApp, postfix); + manifest.addUiApplication(uiApp); + isAdded = true; + + return true; + } + Catch(DPL::Exception) + { + _E("Adding UiApplication on xml is failed."); + isAdded = false; + return false; + } +} +#endif + +DPL::String TaskManifestFile::getIconTargetFilename( + const DPL::String& languageTag, const std::string & ext) const +{ + DPL::OStringStream filename; + TizenAppId appid = m_context.widgetConfig.tzAppid; + + filename << DPL::ToUTF8String(appid).c_str(); + + if (!languageTag.empty()) { + DPL::OptionalString tag = getLangTag(languageTag); // translate en -> + // en_US etc + if (!tag) { + tag = languageTag; + } + DPL::String locale = + LanguageTagsProvider::BCP47LanguageTagToLocale(*tag); + + if (locale.empty()) { + filename << L"." << languageTag; + } else { + filename << L"." << locale; + } + } + + if(!ext.empty()) + { + filename << L"." + DPL::FromUTF8String(ext); + } + return filename.str(); +} + +void TaskManifestFile::saveLocalizedKey(std::ofstream &file, + const DPL::String& key, + const DPL::String& languageTag) +{ + DPL::String locale = + LanguageTagsProvider::BCP47LanguageTagToLocale(languageTag); + + file << key; + if (!locale.empty()) { + file << "[" << locale << "]"; + } + file << "="; +} + +void TaskManifestFile::stepGenerateManifest() +{ + TizenPkgId pkgid = m_context.widgetConfig.tzPkgid; + manifest_name = pkgid + L".xml"; + + // In FOTA environment, Use temporary directory created by pkgmgr. + // Becuase /tmp can be read-only filesystem. + if (m_context.mode.installTime == InstallMode::InstallTime::FOTA) { + manifest_file += L"/opt/share/packages/.recovery/wgt/" + manifest_name; + } else { + manifest_file += L"/tmp/" + manifest_name; + } + + //libxml - init and check + LibxmlSingleton::Instance().init(); + + writeManifest(manifest_file); + + std::ostringstream destFile; + if (m_context.mode.rootPath == InstallMode::RootPath::RO) { + destFile << WrtDB::GlobalConfig::GetPreloadManifestPath() << "/"; + } else { + destFile << WrtDB::GlobalConfig::GetManifestPath() << "/"; + } + + destFile << DPL::ToUTF8String(manifest_name); + commit_manifest = destFile.str(); + _D("Commiting manifest file : %s", commit_manifest.c_str()); + + commitManifest(); + + m_context.job->UpdateProgress( + InstallerContext::INSTALL_CREATE_MANIFEST, + "Widget Manifest Creation Finished"); +} + +void TaskManifestFile::commitManifest() +{ + + if (!(m_context.mode.rootPath == InstallMode::RootPath::RO && + (m_context.mode.installTime == InstallMode::InstallTime::PRELOAD + || m_context.mode.installTime == InstallMode::InstallTime::FOTA) + && m_context.mode.extension == InstallMode::ExtensionType::DIR)) { + _D("cp %ls %s", manifest_file.c_str(), commit_manifest.c_str()); + + DPL::FileInput input(DPL::ToUTF8String(manifest_file)); + DPL::FileOutput output(commit_manifest); + DPL::Copy(&input, &output); + _D("Manifest writen to: %s", commit_manifest.c_str()); + + //removing temp file + unlink((DPL::ToUTF8String(manifest_file)).c_str()); + manifest_file = DPL::FromUTF8String(commit_manifest); + } +} + +void TaskManifestFile::writeManifest(const DPL::String & path) +{ + _D("Generating manifest file : %ls", path.c_str()); + Manifest manifest; + UiApplication uiApp; + +#ifdef MULTIPROCESS_SERVICE_SUPPORT + //default widget content + std::stringstream postfix; + // index 0 is reserved + postfix << AppControlPrefix::PROCESS_PREFIX << 0; + setWidgetExecPath(uiApp, postfix.str()); + setWidgetName(manifest, uiApp); + setWidgetIds(manifest, uiApp); + setWidgetIcons(uiApp); + setWidgetDescription(manifest); + setWidgetManifest(manifest); + setWidgetOtherInfo(uiApp); + setAppCategory(uiApp); + setMetadata(uiApp); + // move to the last of this procedure + //setLiveBoxInfo(manifest); + setAccount(manifest); + setPrivilege(manifest); + manifest.addUiApplication(uiApp); + + //app-control content + ConfigParserData::AppControlInfoList appControlList = + m_context.widgetConfig.configInfo.appControlList; + FOREACH(it, appControlList) { + UiApplication uiApp; + + uiApp.setTaskmanage(true); + uiApp.setNodisplay(true); +#ifdef MULTIPROCESS_SERVICE_SUPPORT_INLINE + uiApp.setTaskmanage(ConfigParserData::AppControlInfo::Disposition::INLINE != it->m_disposition); + uiApp.setMultiple(ConfigParserData::AppControlInfo::Disposition::INLINE == it->m_disposition); +#endif + std::stringstream postfix; + postfix << AppControlPrefix::PROCESS_PREFIX << it->m_index; + setWidgetExecPath(uiApp, postfix.str()); + setWidgetName(manifest, uiApp); + setWidgetIds(manifest, uiApp); + setWidgetIcons(uiApp); + setAppControlInfo(uiApp, *it); + setAppCategory(uiApp); + setMetadata(uiApp); + manifest.addUiApplication(uiApp); + } + // TODO: Must fix again with right method + // The mainapp attiribute must be set + // when there are multiple uiapps in mainfest +#ifdef SERVICE_ENABLED + WrtDB::ConfigParserData::ServiceAppInfoList service = m_context.widgetConfig.configInfo.serviceAppInfoList; + + if (service.size() > 0) { + ConfigParserData &data = m_context.widgetConfig.configInfo; + + FOREACH(it, service) { + ServiceApplication serviceApp; + setServiceInfo(serviceApp, *it); + manifest.addServiceApplication(serviceApp); + } + } else { + _D("Widget doesn't contain service"); + } +#endif + +#ifdef IME_ENABLED + ImeApplication imeApp; + WrtDB::ConfigParserData::ImeAppInfoList ime = m_context.widgetConfig.configInfo.imeAppInfoList; + + if (ime.size() > 0) { + extractImeInfo(imeApp); + manifest.addImeApplication(imeApp); + } else { + _D("Widget doesn't contain ime"); + } +#endif + +#ifdef DBOX_ENABLED + setLiveBoxInfo(manifest); +#endif +#else + //default widget content + setWidgetExecPath(uiApp); + setWidgetName(manifest, uiApp); + setWidgetIds(manifest, uiApp); + setWidgetIcons(uiApp); + setWidgetDescription(manifest); + setWidgetManifest(manifest); + setWidgetOtherInfo(uiApp); + setAppControlsInfo(uiApp); + setAppCategory(uiApp); + setMetadata(uiApp); + // move to the last of this procedure + //setLiveBoxInfo(manifest); + setAccount(manifest); + setPrivilege(manifest); + + manifest.addUiApplication(uiApp); + // TODO: Must fix again with right method + // The mainapp attiribute must be set + // when there are multiple uiapps in mainfest + +#ifdef SERVICE_ENABLED + WrtDB::ConfigParserData::ServiceAppInfoList service = m_context.widgetConfig.configInfo.serviceAppInfoList; + + if (service.size() > 0) { + ConfigParserData &data = m_context.widgetConfig.configInfo; + + FOREACH(it, service) { + ServiceApplication serviceApp; + setServiceInfo(serviceApp, *it); + manifest.addServiceApplication(serviceApp); + } + } else { + _D("Widget doesn't contain service"); + } +#endif + +#ifdef IME_ENABLED + ImeApplication imeApp; + WrtDB::ConfigParserData::ImeAppInfoList ime = m_context.widgetConfig.configInfo.imeAppInfoList; + + if (ime.size() > 0) { + extractImeInfo(imeApp); + manifest.addImeApplication(imeApp); + } else { + _D("Widget doesn't contain ime"); + } +#endif + +#ifdef DBOX_ENABLED + setLiveBoxInfo(manifest); +#endif +#endif + + manifest.generate(path); + _D("Manifest file serialized"); +} + +#ifdef SERVICE_ENABLED +void TaskManifestFile::setServiceInfo(ServiceApplication &serviceApp, WrtDB::ConfigParserData::ServiceAppInfo & service) +{ + setWidgetExecPathService(serviceApp, service); + setWidgetIdsService(serviceApp, service); + setWidgetNameService(serviceApp, service); + setWidgetIconService(serviceApp, service); + setAppControlsInfoService(serviceApp); + setWidgetOtherInfoService(serviceApp); + setWidgetComponentService(serviceApp); + setWidgetAutoRestartService(serviceApp, service); + setWidgetOnBootService(serviceApp, service); +} + +void TaskManifestFile::setWidgetComponentService(ServiceApplication &serviceApp) +{ + serviceApp.setComponent(DPL::FromASCIIString("svcapp")); +} + +void TaskManifestFile::setWidgetAutoRestartService(ServiceApplication &serviceApp, const WrtDB::ConfigParserData::ServiceAppInfo & service) +{ + serviceApp.setAutoRestart(service.autoRestart); +} + +void TaskManifestFile::setWidgetOnBootService(ServiceApplication &serviceApp, const WrtDB::ConfigParserData::ServiceAppInfo & service) +{ + serviceApp.setOnBoot(service.onBoot); +} + +void TaskManifestFile::setWidgetExecPathService(ServiceApplication &serviceApp, const WrtDB::ConfigParserData::ServiceAppInfo & service) +{ + if (service.serviceId.empty()) { + _D("Widget doesn't contain service id"); + return; + } + + std::string serviceExec = m_context.locations->getBinaryDir() + "/" + DPL::ToUTF8String(service.serviceId); + serviceApp.setExec(DPL::FromUTF8String(serviceExec)); +} + +void TaskManifestFile::setWidgetIdsService(ServiceApplication &serviceApp, const WrtDB::ConfigParserData::ServiceAppInfo & service) +{ + //appid + if (service.serviceId.empty()) { + _D("Widget doesn't contain service id"); + return; + } + serviceApp.setAppid(service.serviceId); + + //extraid + TizenAppId appid = m_context.widgetConfig.tzAppid; + if (!!m_context.widgetConfig.guid) { + serviceApp.setExtraid(*m_context.widgetConfig.guid); + } else { + if (!appid.empty()) { + serviceApp.setExtraid(DPL::String(L"http://") + appid); + } + } + + //type + serviceApp.setType(DPL::FromASCIIString("capp")); +} + +void TaskManifestFile::setWidgetNameService(ServiceApplication &serviceApp, WrtDB::ConfigParserData::ServiceAppInfo & service) +{ + if (service.m_localizedDataSet.empty()) { + _D("Widget doesn't contain service name"); + return; + } + + ConfigParserData::LocalizedDataSet &localizedDataSet = service.m_localizedDataSet; + FOREACH(localizedData, localizedDataSet) { + Locale i = localizedData->first; + DPL::OptionalString localeTag = getLangTag(i); + if (localeTag.IsNull()) { + localeTag = i; + } + DPL::OptionalString name = localizedData->second.name; + + if (!!name) { + if (!!localeTag) { + DPL::String locale = + LanguageTagsProvider::BCP47LanguageTagToLocale(*localeTag); + + if (!locale.empty()) { + serviceApp.addLabel(LabelType(*name, *localeTag)); + } else { + serviceApp.addLabel(LabelType(*name)); + } + } else { + serviceApp.addLabel(LabelType(*name)); + } + } + } +} + +void TaskManifestFile::setWidgetIconService(ServiceApplication & serviceApp, const WrtDB::ConfigParserData::ServiceAppInfo & service) +{ + if (service.m_iconsList.empty()) { + _D("Widget doesn't contain service icon"); + return; + } + + DPL::String icon = + DPL::FromUTF8String(m_context.locations->getSharedResourceDir()) + + DPL::String(L"/") + + DPL::String(service.serviceId) + DPL::String(L".png"); + serviceApp.addIcon(icon); +} + +void TaskManifestFile::setAppControlsInfoService(ServiceApplication & serviceApp) +{ + WrtDB::ConfigParserData::AppControlInfoList appControlList = + m_context.widgetConfig.configInfo.appControlList; + + if (appControlList.empty()) { + _D("Widget doesn't contain app control"); + return; + } + + // x-tizen-svc=http://tizen.org/appcontrol/operation/pick|NULL|image; + FOREACH(it, appControlList) { + setAppControlInfoService(serviceApp, *it); + } +} + +void TaskManifestFile::setAppControlInfoService(ServiceApplication & serviceApp, + const WrtDB::ConfigParserData::AppControlInfo & service) +{ + // x-tizen-svc=http://tizen.org/appcontrol/operation/pick|NULL|image; + AppControl appControl; + if (!service.m_operation.empty()) { + appControl.addOperation(service.m_operation); //TODO: encapsulation? + } + if (!service.m_uriList.empty()) { + FOREACH(uri, service.m_uriList) { + appControl.addUri(*uri); + } + } + if (!service.m_mimeList.empty()) { + FOREACH(mime, service.m_mimeList) { + appControl.addMime(*mime); + } + } + serviceApp.addAppControl(appControl); +} + +void TaskManifestFile::setWidgetOtherInfoService(ServiceApplication &serviceApp) +{ + serviceApp.setNodisplay(true); + serviceApp.setTaskmanage(false); + serviceApp.setMultiple(false); + + FOREACH(it, m_context.widgetConfig.configInfo.settingsList) + { + if (!strcmp(DPL::ToUTF8String(it->m_name).c_str(), STR_NODISPLAY)) { + if (!strcmp(DPL::ToUTF8String(it->m_value).c_str(), STR_TRUE)) { + serviceApp.setNodisplay(true); + serviceApp.setTaskmanage(false); + } else { + serviceApp.setNodisplay(false); + serviceApp.setTaskmanage(true); + } + } + } +} +#endif + +#ifdef IME_ENABLED +void TaskManifestFile::extractImeInfo(ImeApplication &imeApp) +{ + setWidgetNameIME(imeApp); + setWidgetIdsIME(imeApp); + setWidgetUuidIME(imeApp); + setWidgetLanguageIME(imeApp); + setWidgetTypeIME(imeApp); + setWidgetOptionIME(imeApp); +} + +void TaskManifestFile::setWidgetUuidIME(ImeApplication &imeApp) +{ + WrtDB::ConfigParserData::ImeAppInfoList ime = m_context.widgetConfig.configInfo.imeAppInfoList; + + FOREACH(it, ime) + { + imeApp.addUuid(it->uuid); + } +} + +void TaskManifestFile::setWidgetLanguageIME(ImeApplication &imeApp) +{ + WrtDB::ConfigParserData::ImeAppInfoList ime = m_context.widgetConfig.configInfo.imeAppInfoList; + + FOREACH(it, ime) + { + FOREACH(lang, it->languageList) { + imeApp.addLanguage(*lang); + } + } +} + +void TaskManifestFile::setWidgetTypeIME(ImeApplication &imeApp) +{ + imeApp.addIseType(DPL::FromASCIIString("SOFTWARE_KEYBOARD_ISE")); +} + +void TaskManifestFile::setWidgetOptionIME(ImeApplication &imeApp) +{ + imeApp.addOption(DPL::FromASCIIString("STAND_ALONE")); + imeApp.addOption(DPL::FromASCIIString("NEED_SCREEN_INFO")); + imeApp.addOption(DPL::FromASCIIString("AUTO_RESTART")); +} + +void TaskManifestFile::setWidgetIdsIME(ImeApplication & imeApp, const std::string &postfix) +{ + //appid + TizenAppId appid = m_context.widgetConfig.tzAppid; + if (!postfix.empty()) { + appid = DPL::FromUTF8String(DPL::ToUTF8String(appid).append(postfix)); + } + imeApp.setAppid(appid); +} + +void TaskManifestFile::setWidgetNameIME(ImeApplication &imeApp) +{ + bool defaultNameSaved = false; + + DPL::OptionalString defaultLocale = + m_context.widgetConfig.configInfo.defaultlocale; + std::pair defaultLocalizedData; + //labels + FOREACH(localizedData, m_context.widgetConfig.configInfo.localizedDataSet) + { + Locale i = localizedData->first; + DPL::OptionalString tag = getLangTag(i); // translate en -> en_US etc + if (!tag) { + tag = i; + } + DPL::OptionalString name = localizedData->second.name; + generateWidgetNameIME(imeApp, tag, name, defaultNameSaved); + + //store default locale localized data + if (!!defaultLocale && defaultLocale == i) { + defaultLocalizedData = *localizedData; + } + } + + if (!!defaultLocale && !defaultNameSaved) { + DPL::OptionalString name = defaultLocalizedData.second.name; + generateWidgetNameIME(imeApp, + DPL::OptionalString(), + name, + defaultNameSaved); + } +} + +void TaskManifestFile::generateWidgetNameIME(ImeApplication &imeApp, + const DPL::OptionalString& tag, + DPL::OptionalString name, + bool & defaultNameSaved) +{ + if (!!name) { + if (!!tag) { + DPL::String locale = + LanguageTagsProvider::BCP47LanguageTagToLocale(*tag); + + if (!locale.empty()) { + imeApp.addLabel(LabelType(*name, *tag)); + } else { + imeApp.addLabel(LabelType(*name)); + } + } else { + defaultNameSaved = true; + imeApp.addLabel(LabelType(*name)); + } + } +} +#endif + +void TaskManifestFile::setWidgetExecPath(UiApplication & uiApp, + const std::string &postfix) +{ + std::string exec = m_context.locations->getExecFile(); + if (!postfix.empty()) { + exec.append(postfix); + } + _D("exec = %s", exec.c_str()); + uiApp.setExec(DPL::FromASCIIString(exec)); +} + +void TaskManifestFile::setWidgetName(Manifest & manifest, + UiApplication & uiApp) +{ + bool defaultNameSaved = false; + + DPL::OptionalString defaultLocale = + m_context.widgetConfig.configInfo.defaultlocale; + std::pair defaultLocalizedData; + //labels + FOREACH(localizedData, m_context.widgetConfig.configInfo.localizedDataSet) + { + Locale i = localizedData->first; + DPL::OptionalString tag = getLangTag(i); // translate en -> en_US etc + if (!tag) { + tag = i; + } + DPL::OptionalString name = localizedData->second.name; + generateWidgetName(manifest, uiApp, tag, name, defaultNameSaved); + + //store default locale localized data + if (!!defaultLocale && defaultLocale == i) { + defaultLocalizedData = *localizedData; + } + } + + if (!!defaultLocale && !defaultNameSaved) { + DPL::OptionalString name = defaultLocalizedData.second.name; + generateWidgetName(manifest, + uiApp, + DPL::OptionalString(), + name, + defaultNameSaved); + } +} + +void TaskManifestFile::setWidgetIds(Manifest & manifest, + UiApplication & uiApp, + const std::string &postfix) +{ + //appid + TizenAppId appid = m_context.widgetConfig.tzAppid; + if (!postfix.empty()) { + appid = DPL::FromUTF8String(DPL::ToUTF8String(appid).append(postfix)); + } + uiApp.setAppid(appid); + + //extraid + if (!!m_context.widgetConfig.guid) { + uiApp.setExtraid(*m_context.widgetConfig.guid); + } else { + if (!appid.empty()) { + uiApp.setExtraid(DPL::String(L"http://") + appid); + } + } + + //type + uiApp.setType(DPL::FromASCIIString("webapp")); + manifest.setType(L"wgt"); +} + +void TaskManifestFile::generateWidgetName(Manifest & manifest, + UiApplication &uiApp, + const DPL::OptionalString& tag, + DPL::OptionalString name, + bool & defaultNameSaved) +{ + if (!!name) { + if (!!tag) { + DPL::String locale = + LanguageTagsProvider::BCP47LanguageTagToLocale(*tag); + + if (!locale.empty()) { + uiApp.addLabel(LabelType(*name, *tag)); + } else { + uiApp.addLabel(LabelType(*name)); + manifest.addLabel(LabelType(*name)); + } + } else { + defaultNameSaved = true; + uiApp.addLabel(LabelType(*name)); + manifest.addLabel(LabelType(*name)); + } + } +} + +void TaskManifestFile::setWidgetIcons(UiApplication & uiApp) +{ + //TODO this file will need to be updated when user locale preferences + //changes. + bool defaultIconSaved = false; + + DPL::OptionalString defaultLocale = + m_context.widgetConfig.configInfo.defaultlocale; + + std::vector generatedLocales; + WrtDB::WidgetRegisterInfo::LocalizedIconList & icons = + m_context.widgetConfig.localizationData.icons; + + for (WrtDB::WidgetRegisterInfo::LocalizedIconList::const_iterator + icon = icons.begin(); + icon != icons.end(); + ++icon) + { + FOREACH(locale, icon->availableLocales) + { + DPL::String tmp = (icon->isSmall ? L"small_" : L"") + (*locale); + if (std::find(generatedLocales.begin(), generatedLocales.end(), + tmp) != generatedLocales.end()) + { + _D("Skipping - has that locale - already in manifest"); + continue; + } else { + generatedLocales.push_back(tmp); + } + DPL::OptionalString tag = getLangTag(*locale); // translate en -> + // en_US etc + if (!tag) { + tag = *locale; + } + + generateWidgetIcon(uiApp, tag, *locale, DPL::Utils::Path(icon->src).Extension(), icon->isSmall, defaultIconSaved); + } + } + if (!!defaultLocale && !defaultIconSaved) { + generateWidgetIcon(uiApp, DPL::OptionalString(), + DPL::String(), + std::string(), + false, + defaultIconSaved); + } +} + +void TaskManifestFile::generateWidgetIcon(UiApplication & uiApp, + const DPL::OptionalString& tag, + const DPL::String& language, + const std::string & extension, + bool isSmall, + bool & defaultIconSaved) +{ + DPL::String locale; + if (!!tag) { + locale = LanguageTagsProvider::BCP47LanguageTagToLocale(*tag); + } else { + defaultIconSaved = true; + } + + DPL::Utils::Path + iconText(m_context.locations->getSharedResourceDir()); + iconText /= (isSmall ? L"small_" : L"") + getIconTargetFilename(language, extension); + + if (!locale.empty()) { + uiApp.addIcon(IconType(DPL::FromUTF8String(iconText.Fullpath()), locale, isSmall)); + } else { + uiApp.addIcon(IconType(DPL::FromUTF8String(iconText.Fullpath()), isSmall)); + } + + _D("Icon file : %s", iconText.Fullpath().c_str()); + m_context.job->SendProgressIconPath(iconText.Fullpath()); +} + +void TaskManifestFile::setWidgetDescription(Manifest & manifest) +{ + FOREACH(localizedData, m_context.widgetConfig.configInfo.localizedDataSet) + { + Locale i = localizedData->first; + DPL::OptionalString tag = getLangTag(i); // translate en -> en_US etc + if (!tag) { + tag = i; + } + DPL::OptionalString description = localizedData->second.description; + generateWidgetDescription(manifest, tag, description); + } +} + +void TaskManifestFile::generateWidgetDescription(Manifest & manifest, + const DPL::OptionalString& tag, + DPL::OptionalString description) +{ + if (!!description) { + if (!!tag) { + DPL::String locale = + LanguageTagsProvider::BCP47LanguageTagToLocale(*tag); + if (!locale.empty()) { + manifest.addDescription(DescriptionType(*description, locale)); + } else { + manifest.addDescription(DescriptionType(*description)); + } + } else { + manifest.addDescription(DescriptionType(*description)); + } + } +} + +void TaskManifestFile::setWidgetManifest(Manifest & manifest) +{ + manifest.setPackage(m_context.widgetConfig.tzPkgid); + + if (!!m_context.widgetConfig.version) { + manifest.setVersion(*m_context.widgetConfig.version); + } + DPL::String email = (!!m_context.widgetConfig.configInfo.authorEmail ? + *m_context.widgetConfig.configInfo.authorEmail : L""); + DPL::String href = (!!m_context.widgetConfig.configInfo.authorHref ? + *m_context.widgetConfig.configInfo.authorHref : L""); + DPL::String name = (!!m_context.widgetConfig.configInfo.authorName ? + *m_context.widgetConfig.configInfo.authorName : L""); + manifest.addAuthor(Author(email, href, L"", name)); + + if (!m_context.callerPkgId.empty()) { + manifest.setStoreClientId(m_context.callerPkgId); + } + + // set csc path + if (!m_context.mode.cscPath.empty()) { + manifest.setCscPath(DPL::FromUTF8String(m_context.mode.cscPath)); + } +} + +void TaskManifestFile::setWidgetOtherInfo(UiApplication & uiApp) +{ + FOREACH(it, m_context.widgetConfig.configInfo.settingsList) + { + if (!strcmp(DPL::ToUTF8String(it->m_name).c_str(), STR_NODISPLAY)) { + if (!strcmp(DPL::ToUTF8String(it->m_value).c_str(), STR_TRUE)) { + uiApp.setNodisplay(true); + uiApp.setTaskmanage(false); + } else { + uiApp.setNodisplay(false); + uiApp.setTaskmanage(true); + } + } + } + //TODO + //There is no "X-TIZEN-PackageType=wgt" + //There is no X-TIZEN-PackageID in manifest "X-TIZEN-PackageID=" << + // DPL::ToUTF8String(*widgetID).c_str() + //There is no Comment in pkgmgr "Comment=Widget application" + //that were in desktop file +} + +void TaskManifestFile::setAppControlsInfo(UiApplication & uiApp) +{ + WrtDB::ConfigParserData::AppControlInfoList appControlList = + m_context.widgetConfig.configInfo.appControlList; + + if (appControlList.empty()) { + _D("Widget doesn't contain app control"); + return; + } + + // x-tizen-svc=http://tizen.org/appcontrol/operation/pick|NULL|image; + FOREACH(it, appControlList) { + setAppControlInfo(uiApp, *it); + } +} + +void TaskManifestFile::setAppControlInfo(UiApplication & uiApp, + const WrtDB::ConfigParserData::AppControlInfo & service) +{ + // x-tizen-svc=http://tizen.org/appcontrol/operation/pick|NULL|image; + AppControl appControl; + if (!service.m_operation.empty()) { + appControl.addOperation(service.m_operation); //TODO: encapsulation? + } + if (!service.m_uriList.empty()) { + FOREACH(uri, service.m_uriList) { + appControl.addUri(*uri); + } + } + if (!service.m_mimeList.empty()) { + FOREACH(mime, service.m_mimeList) { + appControl.addMime(*mime); + } + } + uiApp.addAppControl(appControl); +} + +void TaskManifestFile::setAppCategory(UiApplication &uiApp) +{ + WrtDB::ConfigParserData::CategoryList categoryList = + m_context.widgetConfig.configInfo.categoryList; + + bool hasPredefinedCategory = false; + FOREACH(it, categoryList) { + if (!(*it).empty()) { + uiApp.addAppCategory(*it); + if (DPL::ToUTF8String(*it) == STR_CATEGORY_WATCH_CLOCK) { + // in case of idle clock, + // nodisplay should be set to true + uiApp.setNodisplay(true); + uiApp.setTaskmanage(false); + hasPredefinedCategory = true; + } +#ifdef IME_ENABLED + else if (DPL::ToUTF8String(*it) == STR_CATEGORY_IME) { + uiApp.setNodisplay(true); + uiApp.setTaskmanage(false); + hasPredefinedCategory = true; + } +#endif +#ifdef SERVICE_ENABLED + else if (DPL::ToUTF8String(*it) == STR_CATEGORY_SERVICE) { + //uiApp.setNodisplay(true); + //uiApp.setTaskmanage(false); + hasPredefinedCategory = true; + } +#endif + else if (DPL::ToUTF8String(*it) == STR_CATEGORY_WATCH_APP) { + hasPredefinedCategory = true; + } + } + } + + // Tizen W feature + // Add default app category (watch_app) except for watch_clock + if(!hasPredefinedCategory) { + // If the nodisplay attribute is true, does not insert any predefined category. + // Some preloaded applications (like font package) shouldn't be visible + // in app-tray and host-manager. + // But, the nodisplay attribute can be set by "partner" or "platform" privilege only. + if (!uiApp.isNoDisplay()) { + uiApp.addAppCategory(DPL::FromASCIIString(STR_CATEGORY_WATCH_APP)); + } + } +} + +void TaskManifestFile::setMetadata(UiApplication &uiApp) +{ + WrtDB::ConfigParserData::MetadataList metadataList = + m_context.widgetConfig.configInfo.metadataList; + + if (metadataList.empty()) { + _D("Web application doesn't contain metadata"); + return; + } + FOREACH(it, metadataList) { + MetadataType metadataType(it->key, it->value); + uiApp.addMetadata(metadataType); + } +} + +#ifdef DBOX_ENABLED +void TaskManifestFile::setLiveBoxInfo(Manifest& manifest) +{ + ConfigParserData::LiveboxList& liveboxList = + m_context.widgetConfig.configInfo.m_livebox; + + if (liveboxList.empty()) { + _D("no livebox"); + return; + } + + if (!addBoxUiApplication(manifest)) { + _D("error during adding UiApplication for d-box"); + return; + } + + FOREACH(it, liveboxList) { + _D("setLiveBoxInfo"); + LiveBoxInfo liveBox; + WrtDB::ConfigParserData::OptionalLiveboxInfo ConfigInfo = *it; + DPL::String appid = m_context.widgetConfig.tzAppid; + + if (ConfigInfo->m_liveboxId != L"") { + liveBox.setLiveboxId(ConfigInfo->m_liveboxId); + } + + if (ConfigInfo->m_primary != L"") { + liveBox.setPrimary(ConfigInfo->m_primary); + } + + if (ConfigInfo->m_autoLaunch != L"") { + liveBox.setAutoLaunch(ConfigInfo->m_autoLaunch); + } + + if (ConfigInfo->m_updatePeriod != L"") { + liveBox.setUpdatePeriod(ConfigInfo->m_updatePeriod); + } + + std::list > boxLabelList; + if (!ConfigInfo->m_label.empty()) { + FOREACH(im, ConfigInfo->m_label) { + std::pair boxSize; + Locale i = (*im).first; + // translate en -> en_US etc + DPL::OptionalString tag = getLangTag(i); + if (!tag) { + tag = i; + } + boxSize.first = (*tag); + boxSize.second = (*im).second; + boxLabelList.push_back(boxSize); + } + liveBox.setLabel(boxLabelList); + } + + DPL::String defaultLocale = + DPL::FromUTF8String(m_context.locations->getPackageInstallationDir()) + + DPL::String(L"/res/wgt/"); + + if (ConfigInfo->m_icon != L"") { + DPL::String icon = + DPL::FromUTF8String(m_context.locations->getSharedDataDir()) + + DPL::String(L"/") + + ConfigInfo->m_liveboxId + DPL::String(L".icon.png"); + liveBox.setIcon(icon); + } + + if (ConfigInfo->m_boxInfo.m_boxSrc.empty() || + ConfigInfo->m_boxInfo.m_boxSize.empty()) + { + _D("Widget doesn't contain box"); + return; + } else { + BoxInfoType box; + if (!ConfigInfo->m_boxInfo.m_boxSrc.empty()) { + if ((0 == ConfigInfo->m_boxInfo.m_boxSrc.compare(0, 4, L"http")) + || (0 == + ConfigInfo->m_boxInfo.m_boxSrc.compare(0, 5, L"https"))) + { + box.boxSrc = ConfigInfo->m_boxInfo.m_boxSrc; + } else { + box.boxSrc = defaultLocale + ConfigInfo->m_boxInfo.m_boxSrc; + } + } + + if (ConfigInfo->m_boxInfo.m_boxMouseEvent == L"true") { + std::string boxType; + if (ConfigInfo->m_type == L"") { + // in case of default livebox + boxType = web_provider_livebox_get_default_type(); + } else { + boxType = DPL::ToUTF8String(ConfigInfo->m_type); + } + + int box_scrollable = + web_provider_plugin_get_box_scrollable(boxType.c_str()); + + if (box_scrollable) { + box.boxMouseEvent = L"true"; + } else { + box.boxMouseEvent = L"false"; + } + } else { + box.boxMouseEvent = L"false"; + } + + if (ConfigInfo->m_boxInfo.m_boxTouchEffect == L"true") { + box.boxTouchEffect = L"true"; + } else { + box.boxTouchEffect= L"false"; + } + + ConfigParserData::LiveboxInfo::BoxSizeList boxSizeList = + ConfigInfo->m_boxInfo.m_boxSize; + FOREACH(it, boxSizeList) { + if (!(*it).m_preview.empty()) { + (*it).m_preview = + DPL::FromUTF8String(m_context.locations->getSharedDataDir()) + + DPL::String(L"/") + + ConfigInfo->m_liveboxId + DPL::String(L".") + + (*it).m_size + DPL::String(L".preview.png"); + } + box.boxSize.push_back((*it)); + } + + if (!ConfigInfo->m_boxInfo.m_pdSrc.empty() + && !ConfigInfo->m_boxInfo.m_pdWidth.empty() + && !ConfigInfo->m_boxInfo.m_pdHeight.empty()) + { + if ((0 == ConfigInfo->m_boxInfo.m_pdSrc.compare(0, 4, L"http")) + || (0 == ConfigInfo->m_boxInfo.m_pdSrc.compare(0, 5, L"https"))) + { + box.pdSrc = ConfigInfo->m_boxInfo.m_pdSrc; + } else { + box.pdSrc = defaultLocale + ConfigInfo->m_boxInfo.m_pdSrc; + } + box.pdWidth = ConfigInfo->m_boxInfo.m_pdWidth; + box.pdHeight = ConfigInfo->m_boxInfo.m_pdHeight; + } + liveBox.setBox(box); + } + manifest.addLivebox(liveBox); + } +} +#endif + +void TaskManifestFile::setAccount(Manifest& manifest) +{ + WrtDB::ConfigParserData::AccountProvider account = + m_context.widgetConfig.configInfo.accountProvider; + + AccountProviderType provider; + + if (account.m_iconSet.empty()) { + _D("Widget doesn't contain Account"); + return; + } + if (account.m_multiAccountSupport) { + provider.multiAccount = L"true"; + } else { + provider.multiAccount = L"false"; + } + provider.appid = m_context.widgetConfig.tzAppid; + + FOREACH(it, account.m_iconSet) { + std::pair icon; + + if (it->first == ConfigParserData::IconSectionType::DefaultIcon) { + icon.first = L"account"; + } else if (it->first == ConfigParserData::IconSectionType::SmallIcon) { + icon.first = L"account-small"; + } + + // account manifest requires absolute path for icon + // /opt/apps/[package]/shared/res/[icon_path] + icon.second = DPL::FromUTF8String(m_context.locations->getSharedResourceDir()) + + DPL::String(L"/") + + it->second; + provider.icon.push_back(icon); + } + + FOREACH(it, account.m_displayNameSet) { + provider.name.push_back(LabelType(it->second, it->first)); + } + + FOREACH(it, account.m_capabilityList) { + provider.capability.push_back(*it); + } + + Account accountInfo; + accountInfo.addAccountProvider(provider); + manifest.addAccount(accountInfo); +} + +void TaskManifestFile::setPrivilege(Manifest& manifest) +{ + WrtDB::ConfigParserData::PrivilegeList privileges = + m_context.widgetConfig.configInfo.privilegeList; + + PrivilegeType privilege; + + FOREACH(it, privileges) + { + privilege.addPrivilegeName(it->name); + } + + manifest.addPrivileges(privilege); +} + +void TaskManifestFile::StartStep() +{ + LOGD("--------- : START ----------"); +} + +void TaskManifestFile::EndStep() +{ + LOGD("--------- : END ----------"); +} + +} //namespace WidgetInstall +} //namespace Jobs diff --git a/src_wearable/jobs/widget_install/task_manifest_file.h b/src_wearable/jobs/widget_install/task_manifest_file.h new file mode 100755 index 0000000..240cc40 --- /dev/null +++ b/src_wearable/jobs/widget_install/task_manifest_file.h @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file task_manifest_file.h + * @author Pawel Sikorski (p.sikorski@samgsung.com) + * @version + * @brief + */ + +#ifndef INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_DESKTOP_FILE_H +#define INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_DESKTOP_FILE_H + +//SYSTEM INCLUDES +#include + +//WRT INCLUDES +#include +#include +#include + +#include + +#include +#include +#include + +#include + +class InstallerContext; + +namespace Jobs { +namespace WidgetInstall { +class TaskManifestFile : + public DPL::TaskDecl +{ + public: + + DECLARE_EXCEPTION_TYPE(DPL::Exception, Base) + DECLARE_EXCEPTION_TYPE(Base, ManifestValidationError) + DECLARE_EXCEPTION_TYPE(Base, ManifestParsingError) + + TaskManifestFile(InstallerContext &inCont); + virtual ~TaskManifestFile(); + + private: + //context data + InstallerContext &m_context; + + //TODO stepAbort + //steps + void stepCreateExecFile(); + void stepCopyIconFiles(); + void stepCopyLiveboxFiles(); + void stepCopyAccountIconFiles(); +#ifdef SERVICE_ENABLED + void stepCopyServiceIconFiles(); +#endif + void stepGenerateManifest(); + void stepCreateLinkNPPluginsFile(); + + void stepAbortParseManifest(); + + void StartStep(); + void EndStep(); + + //private data + std::list icon_list; //TODO: this should be registered as + // external files + std::ostringstream backup_dir; + xmlTextWriterPtr writer; + DPL::String manifest_name; + DPL::String manifest_file; + std::string commit_manifest; + + //private methods + + void writeManifest(const DPL::String & path); + void commitManifest(); + + void setWidgetExecPath(UiApplication & uiApp, + const std::string &postfix = std::string()); + void setWidgetName(Manifest & manifest, + UiApplication & uiApp); + void setWidgetIds(Manifest & manifest, + UiApplication & uiApp, + const std::string &postfix = std::string()); + void setWidgetIcons(UiApplication & uiApp); + void setWidgetDescription(Manifest & manifest); + void setWidgetManifest(Manifest & manifest); + void setWidgetOtherInfo(UiApplication & uiApp); + void setAppControlsInfo(UiApplication & uiApp); + void setAppControlInfo(UiApplication & uiApp, + const WrtDB::ConfigParserData::AppControlInfo & service); + void setAppCategory(UiApplication & uiApp); + void setMetadata(UiApplication & uiApp); + void setLiveBoxInfo(Manifest& manifest); + void setAccount(Manifest& uiApp); + void setPrivilege(Manifest& manifest); + + void generateWidgetName(Manifest & manifest, + UiApplication &uiApp, + const DPL::OptionalString& tag, + DPL::OptionalString name, + bool & defaultNameSaved); + void generateWidgetDescription(Manifest & manifest, + const DPL::OptionalString& tag, + DPL::OptionalString description); + void generateWidgetIcon(UiApplication & uiApp, + const DPL::OptionalString& tag, + const DPL::String& language, const std::string &extension, + bool isSmall, bool & defaultIconSaved); + void copyFile(const std::string& sourceFile, + const std::string& targetFile); + bool addBoxUiApplication(Manifest& manifest); + + //for widget update + DPL::String getIconTargetFilename(const DPL::String& languageTag, + const std::string & ext) const; + + static void saveLocalizedKey(std::ofstream &file, + const DPL::String& key, + const DPL::String& languageTag); + + static const char * encoding; + +#ifdef IME_ENABLED + void extractImeInfo(ImeApplication& imeApp); + void setWidgetNameIME(ImeApplication& imeApp); + void setWidgetIdsIME(ImeApplication& imeApp, const std::string& postfix = std::string()); + void generateWidgetNameIME(ImeApplication& imeApp, const DPL::OptionalString& tag, DPL::OptionalString name, bool& defaultNameSaved); + void setWidgetUuidIME(ImeApplication& imeApp); + void setWidgetLanguageIME(ImeApplication& imeApp); + void setWidgetTypeIME(ImeApplication& imeApp); + void setWidgetOptionIME(ImeApplication& imeApp); +#endif + +#ifdef SERVICE_ENABLED + void setServiceInfo(ServiceApplication& serviceApp, WrtDB::ConfigParserData::ServiceAppInfo & service); + void setWidgetExecPathService(ServiceApplication & serviceApp, const WrtDB::ConfigParserData::ServiceAppInfo & service); + void setWidgetIdsService(ServiceApplication & serviceApp, const WrtDB::ConfigParserData::ServiceAppInfo & service); + void setWidgetNameService(ServiceApplication & serviceApp, WrtDB::ConfigParserData::ServiceAppInfo & service); + void setWidgetIconService(ServiceApplication & serviceApp, const WrtDB::ConfigParserData::ServiceAppInfo & service); + void setAppControlsInfoService(ServiceApplication & serviceApp); + void setAppControlInfoService(ServiceApplication & serviceApp, const WrtDB::ConfigParserData::AppControlInfo & service); + void setWidgetOtherInfoService(ServiceApplication & serviceApp); + void setWidgetComponentService(ServiceApplication & serviceApp); + void setWidgetAutoRestartService(ServiceApplication & serviceApp, const WrtDB::ConfigParserData::ServiceAppInfo & service); + void setWidgetOnBootService(ServiceApplication & serviceApp, const WrtDB::ConfigParserData::ServiceAppInfo & service); +#endif +}; +} //namespace WidgetInstall +} //namespace Jobs + +#endif /* INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_DESKTOP_FILE_H */ diff --git a/src_wearable/jobs/widget_install/task_pkg_info_update.cpp b/src_wearable/jobs/widget_install/task_pkg_info_update.cpp new file mode 100644 index 0000000..942cca2 --- /dev/null +++ b/src_wearable/jobs/widget_install/task_pkg_info_update.cpp @@ -0,0 +1,281 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file task_pkg_info_update.cpp + * @author Soyoung Kim (sy037.kim@samsung.com) + * @version 1.0 + * @brief Implementation file for installer task information about package + * update + */ +#include "task_pkg_info_update.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +using namespace WrtDB; + +namespace { +} + +namespace Jobs { +namespace WidgetInstall { +TaskPkgInfoUpdate::TaskPkgInfoUpdate(InstallerContext& context) : + DPL::TaskDecl(this), + m_context(context) +{ + AddStep(&TaskPkgInfoUpdate::StartStep); + AddStep(&TaskPkgInfoUpdate::StepPkgInfo); + AddStep(&TaskPkgInfoUpdate::StepSetCertiInfo); + AddStep(&TaskPkgInfoUpdate::EndStep); + AddStep(&TaskPkgInfoUpdate::StepSetEndofInstallation); + + AddAbortStep(&TaskPkgInfoUpdate::StepAbortCertiInfo); + AddAbortStep(&TaskPkgInfoUpdate::stepAbortParseManifest); +} + +void TaskPkgInfoUpdate::StepPkgInfo() +{ + int code = 0; + char* updateTags[3] = {NULL, }; + + char preloadTrue[] = "preload=true"; + char removableTrue[] = "removable=true"; + char removableFalse[] = "removable=false"; + + if (InstallMode::InstallTime::CSC == m_context.mode.installTime + || InstallMode::InstallTime::PRELOAD == m_context.mode.installTime) { + updateTags[0] = preloadTrue; + if (m_context.mode.removable) { + updateTags[1] = removableTrue; + } else { + updateTags[1] = removableFalse; + } + updateTags[2] = NULL; + } + + if (m_context.mode.rootPath == InstallMode::RootPath::RO) { + m_manifest += "/usr/share/packages/"; + } else { + m_manifest += "/opt/share/packages/"; + } + m_manifest += DPL::ToUTF8String(m_context.widgetConfig.tzPkgid) + ".xml"; + _D("manifest file : %s", m_manifest.c_str()); + + if (m_context.isUpdateMode || ( + m_context.mode.rootPath == InstallMode::RootPath::RO + && (m_context.mode.installTime == InstallMode::InstallTime::PRELOAD + || m_context.mode.installTime == InstallMode::InstallTime::FOTA) + && m_context.mode.extension == InstallMode::ExtensionType::DIR)) { + + code = pkgmgr_parser_parse_manifest_for_upgrade( + m_manifest.c_str(), (updateTags[0] == NULL) ? NULL : updateTags); + + if (code != 0) { + _E("Manifest parser error: %d", code); + ThrowMsg(Exceptions::ManifestInvalid, "Parser returncode: " << code); + } + } else { + code = pkgmgr_parser_parse_manifest_for_installation( + m_manifest.c_str(), (updateTags[0] == NULL) ? NULL : updateTags); + + if (code != 0) { + _E("Manifest parser error: %d", code); + ThrowMsg(Exceptions::ManifestInvalid, "Parser returncode: " << code); + } + } + + m_context.job->UpdateProgress( + InstallerContext::INSTALL_PKGINFO_UPDATE, + "Manifest Update Finished"); + _D("Manifest parsed"); +} + +void TaskPkgInfoUpdate::StepSetCertiInfo() +{ + _D("StepSetCertiInfo"); + + if (pkgmgr_installer_create_certinfo_set_handle(&m_pkgHandle) < 0) { + _E("pkgmgrInstallerCreateCertinfoSetHandle fail"); + ThrowMsg(Exceptions::SetCertificateInfoFailed, + "Failed to create certificate handle"); + } + + SetCertiInfo(SIGNATURE_AUTHOR); + SetCertiInfo(SIGNATURE_DISTRIBUTOR); + SetCertiInfo(SIGNATURE_DISTRIBUTOR2); + + if ((pkgmgr_installer_save_certinfo( + const_cast(DPL::ToUTF8String( + m_context.widgetConfig.tzPkgid).c_str()), + m_pkgHandle)) < 0) + { + _E("pkgmgrInstallerSaveCertinfo fail"); + ThrowMsg(Exceptions::SetCertificateInfoFailed, + "Failed to Installer Save Certinfo"); + } else { + _D("Succeed to save Certinfo"); + } + + if (pkgmgr_installer_destroy_certinfo_set_handle(m_pkgHandle) < 0) { + _E("pkgmgrInstallerDestroyCertinfoSetHandle fail"); + } +} + +void TaskPkgInfoUpdate::SetCertiInfo(int source) +{ + _D("Set CertiInfo to pkgmgr : %d", source); + CertificateChainList certificateChainList; + m_context.widgetSecurity.getCertificateChainList(certificateChainList, + (CertificateSource)source); + + FOREACH(it, certificateChainList) + { + _D("Insert certinfo to pkgmgr structure"); + + ValidationCore::CertificateCollection chain; + + if (false == chain.load(*it)) { + _E("Chain is broken"); + ThrowMsg(Exceptions::SetCertificateInfoFailed, + "Failed to Installer Save Certinfo"); + } + + if (!chain.sort()) { + _E("Chain failed at sorting"); + } + + ValidationCore::CertificateList list = chain.getCertificateList(); + + FOREACH(certIt, list) + { + pkgmgr_instcert_type instCertType = PM_SET_AUTHOR_ROOT_CERT; + if (source == SIGNATURE_AUTHOR) { + _D("set SIGNATURE_AUTHOR"); + if ((*certIt)->isRootCert()) { + instCertType = PM_SET_AUTHOR_ROOT_CERT; + } else { + if ((*certIt)->isCA()) { + instCertType = PM_SET_AUTHOR_INTERMEDIATE_CERT; + } else { + instCertType = PM_SET_AUTHOR_SIGNER_CERT; + } + } + } else if (source == SIGNATURE_DISTRIBUTOR) { + _D("Set SIGNATURE_DISTRIBUTOR"); + if ((*certIt)->isRootCert()) { + instCertType = PM_SET_DISTRIBUTOR_ROOT_CERT; + } else { + if ((*certIt)->isCA()) { + instCertType = PM_SET_DISTRIBUTOR_INTERMEDIATE_CERT; + } else { + instCertType = PM_SET_DISTRIBUTOR_SIGNER_CERT; + } + } + } else if (source == SIGNATURE_DISTRIBUTOR2) { + _D("Set SIGNATURE_DISTRIBUTOR2"); + if ((*certIt)->isRootCert()) { + instCertType = PM_SET_DISTRIBUTOR2_ROOT_CERT; + } else { + if ((*certIt)->isCA()) { + instCertType = PM_SET_DISTRIBUTOR2_INTERMEDIATE_CERT; + } else { + instCertType = PM_SET_DISTRIBUTOR2_SIGNER_CERT; + } + } + } else { + _D("UNKNOWN.."); + } + _D("cert type : %d", instCertType); + if ((pkgmgr_installer_set_cert_value( + m_pkgHandle, + instCertType, + const_cast(((*certIt)->getBase64()).c_str()))) < 0) + { + _E("pkgmgrInstallerSetCertValue fail"); + ThrowMsg(Exceptions::SetCertificateInfoFailed, + "Failed to Set CertValue"); + } + } + } +} + +void TaskPkgInfoUpdate::StepAbortCertiInfo() +{ + if ((pkgmgr_installer_delete_certinfo( + const_cast(DPL::ToUTF8String( + m_context.widgetConfig.tzPkgid).c_str()))) < + 0) + { + _E("pkgmgr_installer_delete_certinfo fail"); + } +} + +void TaskPkgInfoUpdate::StartStep() +{ + LOGD("--------- : START ----------"); +} + +void TaskPkgInfoUpdate::EndStep() +{ + m_context.job->UpdateProgress( + InstallerContext::INSTALL_SET_CERTINFO, + "Save certinfo to pkgmgr"); + + LOGD("--------- : END ----------"); +} + +void TaskPkgInfoUpdate::stepAbortParseManifest() +{ + _E("[Parse Manifest] Abroting...."); + + int code = pkgmgr_parser_parse_manifest_for_uninstallation( + m_manifest.c_str(), NULL); + + if (0 != code) { + _W("Manifest parser error: %d", code); + ThrowMsg(Exceptions::ManifestInvalid, "Parser returncode: " << code); + } + int ret = unlink(m_manifest.c_str()); + if (0 != ret) { + _W("No manifest file found: %s", m_manifest.c_str()); + } +} + +void TaskPkgInfoUpdate::StepSetEndofInstallation() +{ + m_context.job->UpdateProgress( + InstallerContext::INSTALL_END, + "End installation"); +} + +} //namespace WidgetInstall +} //namespace Jobs diff --git a/src_wearable/jobs/widget_install/task_pkg_info_update.h b/src_wearable/jobs/widget_install/task_pkg_info_update.h new file mode 100644 index 0000000..e1e9235 --- /dev/null +++ b/src_wearable/jobs/widget_install/task_pkg_info_update.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file task_pkg_info_update.h + * @author soyoung kim (sy037.kim@samsung.com) + * @version 1.0 + */ + +#ifndef SRC_JOBS_WIDGET_INSTALL_TASK_PKG_INFO_UPDATE_H_ +#define SRC_JOBS_WIDGET_INSTALL_TASK_PKG_INFO_UPDATE_H_ + +#include +#include +#include + +class InstallerContext; + +namespace Jobs { +namespace WidgetInstall { +class TaskPkgInfoUpdate : public DPL::TaskDecl +{ + private: + // Installation context + InstallerContext &m_context; + + void StepPkgInfo(); + void StepSetCertiInfo(); + void SetCertiInfo(int source); + void StepSetEndofInstallation(); + + void stepAbortParseManifest(); + void StepAbortCertiInfo(); + + void StartStep(); + void EndStep(); + + pkgmgr_instcertinfo_h m_pkgHandle; + std::string m_manifest; + + public: + explicit TaskPkgInfoUpdate(InstallerContext &installerContext); +}; +} // namespace WidgetInstall +} // namespace Jobs +#endif /* SRC_JOBS_WIDGET_INSTALL_TASK_PKG_INFO_UPDATE_H_ */ diff --git a/src_wearable/jobs/widget_install/task_prepare_files.cpp b/src_wearable/jobs/widget_install/task_prepare_files.cpp new file mode 100644 index 0000000..d8eac2e --- /dev/null +++ b/src_wearable/jobs/widget_install/task_prepare_files.cpp @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file task_generate_config.cpp + * @author Krzysztof Jackiewicz (k.jackiewicz@samsung.com) + * @version 1.0 + */ + +#include "task_prepare_files.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Jobs { +namespace WidgetInstall { +TaskPrepareFiles::TaskPrepareFiles(InstallerContext &installerContext) : + DPL::TaskDecl(this), + m_installerContext(installerContext) +{ + AddStep(&TaskPrepareFiles::StartStep); + AddStep(&TaskPrepareFiles::StepCopyFiles); + AddStep(&TaskPrepareFiles::EndStep); +} + +void TaskPrepareFiles::CopyFile(const std::string& source) +{ + if (source.empty()) { + _W("No source file specified"); + return; + } + + std::string filename = source; + size_t last = source.find_last_of("\\/"); + if (last != std::string::npos) { + filename = source.substr(last + 1); + } + std::string target = + m_installerContext.locations->getSourceDir() + '/' + + filename; + _D("source %s", source.c_str()); + _D("target %s", target.c_str()); + + Try + { + DPL::FileInput input(source); + DPL::FileOutput output(target); + DPL::Copy(&input, &output); + } + Catch(DPL::FileInput::Exception::Base) + { + _E("File input error"); + // Error while opening or closing source file + ReThrowMsg(Exceptions::CopyIconFailed, source); + } + Catch(DPL::FileOutput::Exception::Base) + { + _E("File output error"); + // Error while opening or closing target file + ReThrowMsg(Exceptions::CopyIconFailed, target); + } + Catch(DPL::CopyFailed) + { + _E("File copy error"); + // Error while copying + ReThrowMsg(Exceptions::CopyIconFailed, target); + } +} + +void TaskPrepareFiles::StepCopyFiles() +{ + CopyFile(m_installerContext.locations->getWidgetSource()); + + size_t last = m_installerContext.locations->getWidgetSource().find_last_of( + "\\/"); + std::string sourceDir = ""; + if (last != std::string::npos) { + sourceDir = m_installerContext.locations->getWidgetSource().substr( + 0, + last + + 1); + } + + _D("Icons copy..."); + FOREACH(it, m_installerContext.widgetConfig.configInfo.iconsList) { + std::ostringstream os; + _D("Coping: %s%ls", sourceDir.c_str(), (it->src).c_str()); + os << sourceDir << DPL::ToUTF8String(it->src); + CopyFile(os.str()); + } +} + +void TaskPrepareFiles::StartStep() +{ + LOGD("--------- : START ----------"); +} + +void TaskPrepareFiles::EndStep() +{ + LOGD("--------- : END ----------"); +} +} // namespace WidgetInstall +} // namespace Jobs diff --git a/src_wearable/jobs/widget_install/task_prepare_files.h b/src_wearable/jobs/widget_install/task_prepare_files.h new file mode 100644 index 0000000..99458e8 --- /dev/null +++ b/src_wearable/jobs/widget_install/task_prepare_files.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file task_prepare_files.h + * @author Krzysztof Jackiewicz (k.jackiewicz@samsung.com) + * @version 1.0 + */ + +#ifndef SRC_JOBS_WIDGET_INSTALL_TASK_PREPARE_FILES_H_ +#define SRC_JOBS_WIDGET_INSTALL_TASK_PREPARE_FILES_H_ + +#include +#include + +class InstallerContext; + +namespace Jobs { +namespace WidgetInstall { +class TaskPrepareFiles : public DPL::TaskDecl +{ + private: + // Installation context + InstallerContext &m_installerContext; + + void CopyFile(const std::string& source); + + // Steps + void StepCopyFiles(); + + void StartStep(); + void EndStep(); + + public: + explicit TaskPrepareFiles(InstallerContext &installerContext); +}; +} // namespace WidgetInstall +} // namespace Jobs +#endif /* SRC_JOBS_WIDGET_INSTALL_TASK_PREPARE_FILES_H_ */ diff --git a/src_wearable/jobs/widget_install/task_prepare_reinstall.cpp b/src_wearable/jobs/widget_install/task_prepare_reinstall.cpp new file mode 100644 index 0000000..97133bf --- /dev/null +++ b/src_wearable/jobs/widget_install/task_prepare_reinstall.cpp @@ -0,0 +1,258 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file task_prepare_reinstall.cpp + * @author Jihoon Chung(jihoon.chung@samsung.com) + * @version 1.0 + * @brief Implementation file for installer task prepare reinstalling + */ + +#include "task_prepare_reinstall.h" + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include + +namespace Jobs { +namespace WidgetInstall { +namespace { +const char* const KEY_DELETE = "#delete"; +const char* const KEY_ADD = "#add"; +const char* const KEY_MODIFY = "#modify"; +std::list keyList = {KEY_DELETE, KEY_ADD, KEY_MODIFY}; + +void verifyFile(const std::string &filePath) +{ + if (access(filePath.c_str(), F_OK) != 0) { + ThrowMsg(Exceptions::RDSDeltaFailure, "File is missed " << filePath); + } +} + +std::string parseSubPath(const std::string& filePath) +{ + std::string subPath(""); + size_t pos = filePath.find_last_of('/') + 1; + + if (pos != std::string::npos) { + subPath = filePath.substr(0, pos); + } + return subPath; +} + +void createDir(const std::string& path) +{ + if (WrtUtilMakeDir(path)) { + _D("Create directory : %s", path.c_str()); + } else { + ThrowMsg(Exceptions::RDSDeltaFailure, "Fail to create dir" << path); + } +} +} // namespace anonymous + +TaskPrepareReinstall::TaskPrepareReinstall(InstallerContext& context) : + DPL::TaskDecl(this), + m_context(context) +{ + AddStep(&TaskPrepareReinstall::StartStep); + AddStep(&TaskPrepareReinstall::StepPrepare); + AddStep(&TaskPrepareReinstall::StepParseRDSDelta); + AddStep(&TaskPrepareReinstall::StepVerifyRDSDelta); + AddStep(&TaskPrepareReinstall::StepAddFile); + AddStep(&TaskPrepareReinstall::StepDeleteFile); + AddStep(&TaskPrepareReinstall::StepModifyFile); + AddStep(&TaskPrepareReinstall::EndStep); +} + +void TaskPrepareReinstall::StepPrepare() +{ + _D("Prepare"); + m_sourcePath = m_context.locations->getTemporaryPackageDir(); + m_sourcePath += "/"; + + m_installedPath = m_context.locations->getPackageInstallationDir(); + m_installedPath += "/"; +} + +void TaskPrepareReinstall::StepParseRDSDelta() +{ + _D("parse RDS delta"); + std::string rdsDeltaPath = m_sourcePath; + rdsDeltaPath += ".rds_delta"; + std::ifstream delta(rdsDeltaPath); + + if (!delta.is_open()) { + ThrowMsg(Exceptions::RDSDeltaFailure, "rds_delta file is missed"); + return; + } + + std::string line; + std::string key; + while (std::getline(delta, line) &&!delta.eof()) { + FOREACH(keyIt, keyList) { + if (line == *keyIt) { + _D("find key = [%s]", line.c_str()); + key = line; + break; + } + } + if (key == line || line.empty() || line == "\n") { + continue; + } + if (key == KEY_DELETE) { + m_deleteFileList.push_back(line); + _D("line = [%s]", line.c_str()); + } else if (key == KEY_ADD) { + m_addFileList.push_back(line); + _D("line = [%s]", line.c_str()); + } else if (key == KEY_MODIFY) { + m_modifyFileList.push_back(line); + _D("line = [%s]", line.c_str()); + } + } +} + +void TaskPrepareReinstall::StepVerifyRDSDelta() +{ + _D("verify RDS delta"); + // Verify ADD file + FOREACH(file, m_addFileList) { + std::string addFilePath = m_sourcePath; + addFilePath += *file; + verifyFile(addFilePath); + } + // Verify DELETE file + FOREACH(file, m_deleteFileList) { + std::string deleteFilePath = m_installedPath; + deleteFilePath += *file; + verifyFile(deleteFilePath); + } + // Verify MODIFY file + FOREACH(file, m_modifyFileList) { + std::string newFilePath = m_sourcePath; + newFilePath += *file; + verifyFile(newFilePath); + + std::string existingFilePath = m_installedPath; + existingFilePath += *file; + verifyFile(existingFilePath); + } + _D("Finished veify RDS Delta"); + + m_context.job->UpdateProgress( + InstallerContext::INSTALL_RDS_DELTA_CHECK, + "RDS delta verify finished"); +} + +void TaskPrepareReinstall::StepAddFile() +{ + _D("Add file"); + FOREACH(file, m_addFileList) { + std::string newfile = m_sourcePath; + newfile += *file; + std::string destPath = m_installedPath; + destPath += *file; + + if (WrtUtilDirExists(newfile)) { + // In case of a new directory + createDir(destPath); + } else { + // In case of a new file + + // Parse directory and file separately + std::string subPath = parseSubPath(destPath); + if (subPath.empty()) { + ThrowMsg(Exceptions::RDSDeltaFailure, + "Invalid path given" << destPath); + } + + // Create a new directory + createDir(subPath); + + // Add file + if (rename(newfile.c_str(), destPath.c_str()) != 0) { + ThrowMsg(Exceptions::RDSDeltaFailure, + "Fail to add file " << newfile); + } + _D("Add %s to %s", newfile.c_str(), destPath.c_str()); + } + } +} + +void TaskPrepareReinstall::StepDeleteFile() +{ + _D("Delete file"); + FOREACH(file, m_deleteFileList) { + std::string deleteFilePath = m_installedPath; + deleteFilePath += *file; + if (remove(deleteFilePath.c_str()) != 0) { + ThrowMsg(Exceptions::RDSDeltaFailure, + "Fail to DELETE file " << deleteFilePath); + } + _D("Delete %s", deleteFilePath.c_str()); + } +} + +void TaskPrepareReinstall::StepModifyFile() +{ + _D("Modify file"); + FOREACH(file, m_modifyFileList) { + std::string destPath = m_installedPath; + destPath += *file; + if (remove(destPath.c_str()) != 0) { + ThrowMsg(Exceptions::RDSDeltaFailure, + "Fail to delete existing file " << destPath); + } + + std::string newfile = m_sourcePath; + newfile += *file; + if (rename(newfile.c_str(), destPath.c_str()) != 0) { + ThrowMsg(Exceptions::RDSDeltaFailure, + "Fail to move new file" << destPath); + } + _D("Replace %s to %s", newfile.c_str(), destPath.c_str()); + } + + m_context.job->UpdateProgress( + InstallerContext::INSTALL_RDS_PREPARE, + "RDS prepare finished"); +} + +void TaskPrepareReinstall::StartStep() +{ + LOGD("---------- : START ----------"); +} + +void TaskPrepareReinstall::EndStep() +{ + LOGD("---------- : END ----------"); + m_context.job->UpdateProgress( + InstallerContext::INSTALL_END, + "End RDS update"); +} + +} //namespace WidgetInstall +} //namespace Jobs diff --git a/src_wearable/jobs/widget_install/task_prepare_reinstall.h b/src_wearable/jobs/widget_install/task_prepare_reinstall.h new file mode 100644 index 0000000..2828f27 --- /dev/null +++ b/src_wearable/jobs/widget_install/task_prepare_reinstall.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file task_prepare_reinstall.h + * @author Jihoon Chung(jihoon.chung@samsung.com) + * @version 1.0 + * @brief Header file for installer task prepare reinstalling + */ +#ifndef INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_PREPARE_REINSTALL_H +#define INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_PREPARE_REINSTALL_H + +#include +#include + +#include + +class InstallerContext; + +namespace Jobs { +namespace WidgetInstall { +class TaskPrepareReinstall : + public DPL::TaskDecl +{ + public: + TaskPrepareReinstall(InstallerContext& context); + + private: + // install internal location + void StepPrepare(); + void StepParseRDSDelta(); + void StepVerifyRDSDelta(); + void StepAddFile(); + void StepDeleteFile(); + void StepModifyFile(); + + void StepAbortPrepareReinstall(); + + void StartStep(); + void EndStep(); + + InstallerContext& m_context; + // TODO : replace multimap + std::list m_addFileList; + std::list m_deleteFileList; + std::list m_modifyFileList; + std::string m_sourcePath; + std::string m_installedPath; +}; +} //namespace WidgetInstall +} //namespace Jobs + +#endif // INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_PREPARE_REINSTALL_H diff --git a/src_wearable/jobs/widget_install/task_process_config.cpp b/src_wearable/jobs/widget_install/task_process_config.cpp new file mode 100755 index 0000000..4198f4d --- /dev/null +++ b/src_wearable/jobs/widget_install/task_process_config.cpp @@ -0,0 +1,695 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file task_process_config.cpp + * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com) + * @version 1.0 + * @brief Implementation file for installer task widget config + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#ifdef DBOX_ENABLED +#include +#include +#endif +#include + +#include + +namespace { // anonymous +const DPL::String BR = DPL::FromUTF8String("
"); +const std::string WINDGET_INSTALL_NETWORK_ACCESS = "network access"; +} + +namespace Jobs { +namespace WidgetInstall { + +TaskProcessConfig::TaskProcessConfig(InstallerContext& installContext) : + DPL::TaskDecl(this), + m_installContext(installContext) +{ + AddStep(&TaskProcessConfig::StartStep); + AddStep(&TaskProcessConfig::ReadLocaleFolders); + AddStep(&TaskProcessConfig::StepFillWidgetConfig); + AddStep(&TaskProcessConfig::ProcessLocalizedStartFiles); + AddStep(&TaskProcessConfig::ProcessBackgroundPageFile); + AddStep(&TaskProcessConfig::ProcessLocalizedIcons); + AddStep(&TaskProcessConfig::ProcessWidgetInstalledPath); + AddStep(&TaskProcessConfig::ProcessAppControlInfo); + AddStep(&TaskProcessConfig::ProcessSecurityModel); +#ifdef DBOX_ENABLED + AddStep(&TaskProcessConfig::StepVerifyFeatures); +#endif + AddStep(&TaskProcessConfig::StepVerifyLivebox); + AddStep(&TaskProcessConfig::StepCheckMinVersionInfo); + AddStep(&TaskProcessConfig::EndStep); +} + +void TaskProcessConfig::StepFillWidgetConfig() +{ + if (!fillWidgetConfig(m_installContext.widgetConfig, + m_installContext.widgetConfig.configInfo)) + { + _E("Widget configuration is illformed"); + ThrowMsg(Exception::ConfigParseFailed, "Widget configuration is illformed"); + } +} + +void TaskProcessConfig::ReadLocaleFolders() +{ + _D("Reading locale"); + //Adding default locale + m_localeFolders.insert(L""); + + std::string localePath = + m_installContext.locations->getSourceDir() + "/locales"; + + DIR* localeDir = opendir(localePath.c_str()); + if (!localeDir) { + _D("No /locales directory in the widget package."); + return; + } + + struct stat statStruct; + struct dirent dirent; + struct dirent *result; + int return_code; + errno = 0; + for (return_code = readdir_r(localeDir, &dirent, &result); + result != NULL && return_code == 0; + return_code = readdir_r(localeDir, &dirent, &result)) + { + DPL::String dirName = DPL::FromUTF8String(dirent.d_name); + std::string absoluteDirName = localePath + "/"; + absoluteDirName += dirent.d_name; + + if (stat(absoluteDirName.c_str(), &statStruct) != 0) { + _E("stat() failed with %s", DPL::GetErrnoString().c_str()); + continue; + } + + if (S_ISDIR(statStruct.st_mode)) { + //Yes, we ignore current, parent & hidden directories + if (dirName[0] != L'.') { + _D("Adding locale directory \"%ls\"", dirName.c_str()); + m_localeFolders.insert(dirName); + } + } + } + + if (return_code != 0 || errno != 0) { + _E("readdir_r() failed with %s", DPL::GetErrnoString().c_str()); + } + + if (-1 == closedir(localeDir)) { + _E("Failed to close dir: %s with error: %s", localePath.c_str(), DPL::GetErrnoString().c_str()); + } + + m_installContext.job->UpdateProgress(InstallerContext::INSTALL_WIDGET_CONFIG1, "Read locale folders"); +} + +void TaskProcessConfig::ProcessLocalizedStartFiles() +{ + typedef DPL::String S; + ProcessStartFile( + m_installContext.widgetConfig.configInfo.startFile, + m_installContext.widgetConfig.configInfo. + startFileContentType, + m_installContext.widgetConfig.configInfo.startFileEncoding, + true); + ProcessStartFile(S(L"index.htm"), S(L"text/html")); + ProcessStartFile(S(L"index.html"), S(L"text/html")); + ProcessStartFile(S(L"index.svg"), S(L"image/svg+xml")); + ProcessStartFile(S(L"index.xhtml"), S(L"application/xhtml+xml")); + ProcessStartFile(S(L"index.xht"), S(L"application/xhtml+xml")); + // TODO: we need better check if in current locales widget is valid + FOREACH(it, m_installContext.widgetConfig.localizationData.startFiles) { + if (it->propertiesForLocales.size() > 0) { + return; + } + } + ThrowMsg(Exceptions::InvalidStartFile, + "The Widget has no valid start file"); +} + +void TaskProcessConfig::ProcessStartFile(const DPL::OptionalString& path, + const DPL::OptionalString& type, + const DPL::OptionalString& encoding, + bool typeForcedInConfig) +{ + using namespace WrtDB; + + if (!!path) { + WidgetRegisterInfo::LocalizedStartFile startFileData; + startFileData.path = *path; + + FOREACH(i, m_localeFolders) { + DPL::String pathPrefix = *i; + if (!pathPrefix.empty()) { + pathPrefix = L"locales/" + pathPrefix + L"/"; + } + + DPL::String relativePath = pathPrefix + *path; + DPL::String absolutePath = DPL::FromUTF8String( + m_installContext.locations->getSourceDir()) + L"/" + + relativePath; + _D("absolutePath : %ls", absolutePath.c_str()); + + // get property data from packaged app + if (WrtUtilFileExists(DPL::ToUTF8String(absolutePath))) { + WidgetRegisterInfo::StartFileProperties startFileProperties; + if (!!type) { + startFileProperties.type = *type; + } else { + startFileProperties.type = + MimeTypeUtils::identifyFileMimeType(absolutePath); + } + + //proceed only if MIME type is supported + if (MimeTypeUtils::isMimeTypeSupportedForStartFile( + startFileProperties.type)) + { + if (!!encoding) { + startFileProperties.encoding = *encoding; + } else { + MimeTypeUtils::MimeAttributes attributes = + MimeTypeUtils::getMimeAttributes( + startFileProperties.type); + if (attributes.count(L"charset") > 0) { + startFileProperties.encoding = + attributes[L"charset"]; + } else { + startFileProperties.encoding = L"UTF-8"; + } + } + + startFileData.propertiesForLocales[*i] = + startFileProperties; + } else { + //9.1.16.5.content.8 + //(there seems to be no similar requirement in .6, + //so let's throw only when mime type is + // provided explcitly in config.xml) + if (typeForcedInConfig) { + ThrowMsg(Exceptions::WidgetConfigFileInvalid, + "Unsupported MIME type for start file."); + } + } + } else { + // set property data for hosted start url + // Hosted start url only support TIZEN WebApp + if (m_installContext.widgetConfig.webAppType == APP_TYPE_TIZENWEBAPP + ) + { + std::string startPath = DPL::ToUTF8String( + startFileData.path); + + if (strstr(startPath.c_str(), + "http") == startPath.c_str()) + { + WidgetRegisterInfo::StartFileProperties + startFileProperties; + if (!!type) { + startFileProperties.type = *type; + } + if (!!encoding) { + startFileProperties.encoding = *encoding; + } + startFileData.propertiesForLocales[*i] = + startFileProperties; + } + } + } + } + + m_installContext.widgetConfig.localizationData.startFiles.push_back( + startFileData); + } +} + +void TaskProcessConfig::ProcessBackgroundPageFile() +{ + if (!!m_installContext.widgetConfig.configInfo.backgroundPage) { + // check whether file exists + DPL::String backgroundPagePath = DPL::FromUTF8String( + m_installContext.locations->getSourceDir()) + L"/" + + *m_installContext.widgetConfig.configInfo.backgroundPage; + //if no then cancel installation + if (!WrtUtilFileExists(DPL::ToUTF8String(backgroundPagePath))) { + ThrowMsg(Exceptions::WidgetConfigFileInvalid, + L"Given background page file not found in archive"); + } + } +} + +void TaskProcessConfig::ProcessLocalizedIcons() +{ + using namespace WrtDB; + FOREACH(i, m_installContext.widgetConfig.configInfo.iconsList) + { + ProcessIcon(*i); + } + ProcessIcon(ConfigParserData::Icon(L"icon.svg")); + ProcessIcon(ConfigParserData::Icon(L"icon.ico")); + ProcessIcon(ConfigParserData::Icon(L"icon.png")); + ProcessIcon(ConfigParserData::Icon(L"icon.gif")); + ProcessIcon(ConfigParserData::Icon(L"icon.jpg")); +} + +void TaskProcessConfig::ProcessIcon(const WrtDB::ConfigParserData::Icon& icon) +{ + _D("enter"); + bool isAnyIconValid = false; + //In case a default filename is passed as custom filename in config.xml, we + //need to keep a set of already processed filenames to avoid icon + // duplication + //in database. + + using namespace WrtDB; + + std::set &checkDuplication = icon.isSmall ? m_processedSmallIconSet : m_processedIconSet; + + if (checkDuplication.count(icon.src) > 0) { + _D("duplication %ls ", icon.src.c_str()); + return; + } + checkDuplication.insert(icon.src); + + LocaleSet localesAvailableForIcon; + + FOREACH(i, m_localeFolders) + { + DPL::String pathPrefix = *i; + if (!pathPrefix.empty()) { + pathPrefix = L"locales/" + pathPrefix + L"/"; + } + + DPL::String relativePath = pathPrefix + icon.src; + DPL::String absolutePath = DPL::FromUTF8String( + m_installContext.locations->getSourceDir()) + L"/" + + relativePath; + + if (WrtUtilFileExists(DPL::ToUTF8String(absolutePath))) { + DPL::String type = MimeTypeUtils::identifyFileMimeType(absolutePath); + + if (MimeTypeUtils::isMimeTypeSupportedForIcon(type)) { + isAnyIconValid = true; + localesAvailableForIcon.insert(*i); + _D("Icon absolutePath: %ls, assigned locale: %ls, type: %ls", + absolutePath.c_str(), (*i).c_str(), type.c_str()); + } + } + } + + if (isAnyIconValid) { + WidgetRegisterInfo::LocalizedIcon localizedIcon(icon, + localesAvailableForIcon); + m_installContext.widgetConfig.localizationData.icons.push_back( + localizedIcon); + } +} + +void TaskProcessConfig::ProcessWidgetInstalledPath() +{ + _D("ProcessWidgetInstalledPath"); + m_installContext.widgetConfig.widgetInstalledPath = + DPL::FromUTF8String( + m_installContext.locations->getPackageInstallationDir()); +} + +void TaskProcessConfig::ProcessAppControlInfo() +{ + _D("ProcessAppControlInfo"); + using namespace WrtDB; + + // In case of dispostion is inline, set the seperate execute + int index = 1; + // 0 index is reserved by default execute + FOREACH(it, m_installContext.widgetConfig.configInfo.appControlList) { + if (it->m_disposition == + ConfigParserData::AppControlInfo::Disposition::INLINE) + { + it->m_index = index++; + } else { + it->m_index = 0; + } + } +} + +void TaskProcessConfig::ProcessSecurityModel() +{ + // 0104. If the "required_version" specified in the Web Application's + // configuration is 2.2 or higher and if the Web Application's + // configuration is "CSP-compatible configuration", then the WRT MUST be + // set to "CSP-based security mode". Otherwise, the WRT MUST be set to + // "WARP-based security mode". + // 0105. A Web Application configuration is "CSP-compatible configuration" + // if the configuration includes one or more of + // / + // / + // elements. + + bool isSecurityModelV1 = false; + bool isSecurityModelV2 = false; + WrtDB::ConfigParserData &data = m_installContext.widgetConfig.configInfo; + + if (!!data.cspPolicy || + !!data.cspPolicyReportOnly || + !data.allowNavigationInfoList.empty()) + { + data.accessInfoSet.clear(); + } + + // WARP is V1 + if (!data.accessInfoSet.empty()) { + isSecurityModelV1 = true; + } + + // CSP & allow-navigation is V2 + if (!!data.cspPolicy || + !!data.cspPolicyReportOnly || + !data.allowNavigationInfoList.empty()) + { + isSecurityModelV2 = true; + } + + if (isSecurityModelV1 && isSecurityModelV2) { + _E("Security model is conflict"); + ThrowMsg(Exceptions::NotAllowed, "Security model is conflict"); + } else if (isSecurityModelV1) { + data.securityModelVersion = + WrtDB::ConfigParserData::SecurityModelVersion::SECURITY_MODEL_V1; + } else if (isSecurityModelV2) { + data.securityModelVersion = + WrtDB::ConfigParserData::SecurityModelVersion::SECURITY_MODEL_V2; + } else { + data.securityModelVersion = + WrtDB::ConfigParserData::SecurityModelVersion::SECURITY_MODEL_V1; + } + + m_installContext.job->UpdateProgress( + InstallerContext::INSTALL_WIDGET_CONFIG2, + "Finished process security model"); +} + +void TaskProcessConfig::StepCheckMinVersionInfo() +{ + if (!isMinVersionCompatible( + m_installContext.widgetConfig.webAppType.appType, + m_installContext.widgetConfig.minVersion)) + { + _E("Platform version lower than required -> cancelling installation"); + ThrowMsg(Exceptions::NotAllowed, + "Platform version does not meet requirements"); + } + + m_installContext.job->UpdateProgress( + InstallerContext::INSTALL_WIDGET_CONFIG2, + "Check MinVersion Finished"); +} + +void TaskProcessConfig::StepVerifyFeatures() +{ + using namespace WrtDB; + ConfigParserData &data = m_installContext.widgetConfig.configInfo; + ConfigParserData::FeaturesList list = data.featuresList; + ConfigParserData::FeaturesList newList; + + //in case of tests, this variable is unused + std::string featureInfo; + FOREACH(it, list) + { + // check feature vender for permission + // WAC, TIZEN WebApp cannot use other feature + + if (!isFeatureAllowed(m_installContext.widgetConfig.webAppType.appType, + it->name)) + { + _D("This application type not allowed to use this feature"); + ThrowMsg( + Exceptions::WidgetConfigFileInvalid, + "This app type [" << + m_installContext.widgetConfig.webAppType.getApptypeToString() + << + "] cannot be allowed to use [" << + DPL::ToUTF8String(it->name) + "] feature"); + } else { + newList.insert(*it); + featureInfo += DPL::ToUTF8String(it->name); + featureInfo += DPL::ToUTF8String(BR); + } + } + if (!data.accessInfoSet.empty()) { + featureInfo += WINDGET_INSTALL_NETWORK_ACCESS; + featureInfo += DPL::ToUTF8String(BR); + } + data.featuresList = newList; + + m_installContext.job->UpdateProgress( + InstallerContext::INSTALL_WIDGET_CONFIG2, + "Widget Config step2 Finished"); +} + +#ifdef DBOX_ENABLED +void TaskProcessConfig::StepVerifyLivebox() +{ + using namespace WrtDB; + ConfigParserData &data = m_installContext.widgetConfig.configInfo; + ConfigParserData::LiveboxList liveBoxList = data.m_livebox; + + if (liveBoxList.size() <= 0) { + return; + } + + FOREACH (it, liveBoxList) { + std::string boxType; + + size_t found = (**it).m_liveboxId.find_last_of(L"."); + if (found != std::string::npos) { + if (0 != (**it).m_liveboxId.compare(0, found, + m_installContext.widgetConfig.tzAppid)) { + _E("Invalid app-widget id (doesn't begin with application id)"); + ThrowMsg(Exceptions::WidgetConfigFileInvalid, + "Invalid app-widget id(doesn't begin with application id)"); + } + } + + if ((**it).m_type.empty()) { + boxType = web_provider_livebox_get_default_type(); + } else { + boxType = DPL::ToUTF8String((**it).m_type); + } + + _D("livebox type: %s", boxType.c_str()); + + ConfigParserData::LiveboxInfo::BoxSizeList boxSizeList = + (**it).m_boxInfo.m_boxSize; + char** boxSize = static_cast( + malloc(sizeof(char*)* boxSizeList.size())); + + int boxSizeCnt = 0; + FOREACH (m, boxSizeList) { + boxSize[boxSizeCnt++] = strdup(DPL::ToUTF8String((*m).m_size).c_str()); + } + + bool chkSize = web_provider_plugin_check_supported_size( + boxType.c_str(), boxSize, boxSizeCnt); + + for(int i = 0; i < boxSizeCnt; i++) { + free(boxSize[i]); + } + free(boxSize); + + if(!chkSize) { + _E("Invalid boxSize"); + ThrowMsg(Exceptions::WidgetConfigFileInvalid, "Invalid boxSize"); + } + } +} +#endif + +bool TaskProcessConfig::isFeatureAllowed(WrtDB::AppType appType, + DPL::String featureName) +{ + using namespace WrtDB; + _D("AppType = [%s]", WidgetType(appType).getApptypeToString().c_str()); + _D("FetureName = [%ls]", featureName.c_str()); + + AppType featureType = APP_TYPE_UNKNOWN; + std::string featureStr = DPL::ToUTF8String(featureName); + const char* feature = featureStr.c_str(); + + // check prefix of feature name + if (strstr(feature, PluginsPrefix::TIZENPluginsPrefix) == feature) { + // Tizen WebApp feature + featureType = APP_TYPE_TIZENWEBAPP; + } else if (strstr(feature, PluginsPrefix::W3CPluginsPrefix) == feature) { + // W3C standard feature + // Both WAC and TIZEN WebApp are possible to use W3C plugins + return true; + } else { + // unknown feature + // unknown feature will be checked next step + return true; + } + + if (appType == featureType) { + return true; + } + return false; +} + +bool TaskProcessConfig::parseVersionString(const std::string &version, + long &majorVersion, + long &minorVersion, + long µVersion) const +{ + std::istringstream inputString(version); + inputString >> majorVersion; + if (inputString.bad() || inputString.fail()) { + _W("Invalid minVersion format."); + return false; + } + inputString.get(); // skip period + inputString >> minorVersion; + if (inputString.bad() || inputString.fail()) { + _W("Invalid minVersion format"); + return false; + } else { + inputString.get(); // skip period + if (inputString.bad() || inputString.fail()) { + inputString >> microVersion; + } + } + return true; +} + +bool TaskProcessConfig::isMinVersionCompatible( + WrtDB::AppType appType, + const DPL::OptionalString & + widgetVersion) const +{ + if (!widgetVersion || (*widgetVersion).empty()) { + if (appType == WrtDB::AppType::APP_TYPE_TIZENWEBAPP + ) { + return false; + } else { + _W("minVersion attribute is empty. WRT assumes platform " + "supports this widget."); + return true; + } + } + + //Parse widget version + long majorWidget = 0, minorWidget = 0, microWidget = 0; + if (!parseVersionString(DPL::ToUTF8String(*widgetVersion), majorWidget, + minorWidget, microWidget)) + { + _W("Invalid format of widget version string."); + return false; + } + + //Parse supported version + long majorSupported = 0, minorSupported = 0, microSupported = 0; + std::string version; + if (appType == WrtDB::AppType::APP_TYPE_TIZENWEBAPP + ) { + version = WrtDB::GlobalConfig::GetTizenVersion(); + } else { + _W("Invaild AppType"); + return false; + } + + if (!parseVersionString(version, + majorSupported, minorSupported, microSupported)) + { + _W("Invalid format of platform version string."); + return true; + } + + if (majorWidget > majorSupported || + (majorWidget == majorSupported && minorWidget > minorSupported)) + { + _D("Platform doesn't support this widget."); + return false; + } + return true; +} + +bool TaskProcessConfig::isTizenWebApp() const +{ + if (m_installContext.widgetConfig.webAppType.appType == WrtDB::AppType::APP_TYPE_TIZENWEBAPP) + { + return true; + } + return false; +} + +bool TaskProcessConfig::fillWidgetConfig( + WrtDB::WidgetRegisterInfo& pWidgetConfigInfo, + WrtDB::ConfigParserData& configInfo) +{ + pWidgetConfigInfo.guid = configInfo.widget_id; + + if (!!configInfo.version) { + if (!pWidgetConfigInfo.version) { + pWidgetConfigInfo.version = configInfo.version; + } else { + if (pWidgetConfigInfo.version != configInfo.version) { + _E("Invalid archive"); + return false; + } + } + } + if (!!configInfo.minVersionRequired) { + pWidgetConfigInfo.minVersion = configInfo.minVersionRequired; + } else if (!!configInfo.tizenMinVersionRequired) { + pWidgetConfigInfo.minVersion = configInfo.tizenMinVersionRequired; + } + return true; +} + +void TaskProcessConfig::StartStep() +{ + LOGD("--------- : START ----------"); +} + +void TaskProcessConfig::EndStep() +{ + LOGD("--------- : END ----------"); +} + +} //namespace WidgetInstall +} //namespace Jobs diff --git a/src_wearable/jobs/widget_install/task_process_config.h b/src_wearable/jobs/widget_install/task_process_config.h new file mode 100755 index 0000000..fa20264 --- /dev/null +++ b/src_wearable/jobs/widget_install/task_process_config.h @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file task_process_config.h + * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com) + * @version 1.0 + * @brief Implementation file for installer task widget config + */ +#ifndef INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_PROCESS_CONFIG_H +#define INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_PROCESS_CONFIG_H + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +class InstallerContext; + +namespace Jobs { +namespace WidgetInstall { + +class TaskProcessConfig : + public DPL::TaskDecl +{ + private: + class Exception + { + public: + DECLARE_EXCEPTION_TYPE(DPL::Exception, Base) + DECLARE_EXCEPTION_TYPE(Base, ConfigParseFailed) + }; + + typedef std::list > StringPairList; + + InstallerContext& m_installContext; + WrtDB::LocaleSet m_localeFolders; + std::set m_processedIconSet; + std::set m_processedSmallIconSet; + + void StepFillWidgetConfig(); + void ReadLocaleFolders(); + void ProcessLocalizedStartFiles(); + void ProcessStartFile( + const DPL::OptionalString& path, + const DPL::OptionalString& type, + const DPL::OptionalString& encoding = + DPL::OptionalString(), + bool typeForcedInConfig = false); + void ProcessBackgroundPageFile(); + void ProcessLocalizedIcons(); + void ProcessIcon(const WrtDB::ConfigParserData::Icon& icon); + void ProcessWidgetInstalledPath(); + void ProcessAppControlInfo(); + void ProcessSecurityModel(); + void StepVerifyFeatures(); + void StepVerifyLivebox(); + void StepCheckMinVersionInfo(); + + template + void StepCancelInstallation(); + + void StartStep(); + void EndStep(); + + DPL::String createAuthorWidgetInfo() const; + bool isFeatureAllowed( + WrtDB::AppType appType, DPL::String featureName); + bool isMinVersionCompatible( + WrtDB::AppType appType, + const DPL::OptionalString &widgetVersion) const; + /** + * @brief Parses version string in format "major.minor.micro anything" + * Returns false if format is invalid + */ + bool isTizenWebApp() const; + bool parseVersionString(const std::string &version, long &majorVersion, + long &minorVersion, long µVersion) const; + + bool fillWidgetConfig(WrtDB::WidgetRegisterInfo& pWidgetConfigInfo, + WrtDB::ConfigParserData& configInfo); + + public: + TaskProcessConfig(InstallerContext& installTaskContext); +}; +} //namespace WidgetInstall +} //namespace Jobs + +#endif // INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_PROCESS_CONFIG_H diff --git a/src_wearable/jobs/widget_install/task_recovery.cpp b/src_wearable/jobs/widget_install/task_recovery.cpp new file mode 100644 index 0000000..fb2b72a --- /dev/null +++ b/src_wearable/jobs/widget_install/task_recovery.cpp @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file task_recovery.cpp + * @author Soyoung Kim (sy037.kim@samsung.com) + * @version 1.0 + * @brief Implementation file for installer task recovery + */ +#include "task_recovery.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +using namespace WrtDB; + +namespace { +const std::string BACKUP_ID = ".backup"; +} + +namespace Jobs { +namespace WidgetInstall { +TaskRecovery::TaskRecovery(InstallerContext& context) : + DPL::TaskDecl(this), + m_context(context) +{ + AddStep(&TaskRecovery::StartStep); + AddStep(&TaskRecovery::StepRecoveryDirectory); + AddStep(&TaskRecovery::StepRecoveryDatabase); + AddStep(&TaskRecovery::EndStep); +} + +void TaskRecovery::StepRecoveryDirectory() +{ + _D("StepRecoveryDirectory ..."); + // check backup folder + DPL::Utils::Path installedPath(WrtDB::GlobalConfig::GetUserInstalledWidgetPath()); + installedPath /= m_context.widgetConfig.tzPkgid; + + DPL::Utils::Path backupPath(WrtDB::GlobalConfig::GetUserInstalledWidgetPath()); + backupPath /= DPL::ToUTF8String(m_context.widgetConfig.tzPkgid) + BACKUP_ID; + + _D("installedPath : %s", installedPath.Fullpath().c_str()); + _D("backupPath : %s", backupPath.Fullpath().c_str()); + + if (backupPath.Exists()) { + DPL::Utils::TryRemove(installedPath); + + DPL::Utils::Rename(backupPath, installedPath); + } else { + ThrowMsg(Exceptions::RecoveryFailed, "backup folder doesn't exist"); + } +} + +void TaskRecovery::StepRecoveryDatabase() +{ + _D("StepRecoveryDatabase ... %s", m_context.widgetConfig.tzPkgid.c_str()); + Try { + std::string backupId, deleteId; + + TizenAppId dbAppId = WidgetDAOReadOnly::getTizenAppId(m_context.widgetConfig.tzPkgid); + _D("Get appid : %ls", dbAppId.c_str()); + std::string appId = DPL::ToUTF8String(dbAppId); + + if (0 == appId.compare(appId.size() - BACKUP_ID.length(), BACKUP_ID.length(), BACKUP_ID)) { + backupId = appId; + deleteId = backupId.substr(0, backupId.length() - + BACKUP_ID.length()); + } else { + backupId = appId + BACKUP_ID; + deleteId = appId; + } + + if (WrtDB::WidgetDAOReadOnly::isWidgetInstalled(DPL::FromUTF8String(backupId))) { + _D("Recovery Database..."); + _D("backupId %s " , backupId.c_str()); + _D("deleteId %s " , deleteId.c_str()); + + // remove ace + ace_unregister_widget(static_cast( + WidgetDAOReadOnly::getHandle(DPL:: + FromUTF8String(deleteId)))); + ace_unregister_widget(static_cast( + WidgetDAOReadOnly::getHandle(DPL:: + FromUTF8String(backupId)))); + + WidgetDAO::unregisterWidget(DPL::FromUTF8String(deleteId)); + WidgetDAO::updateTizenAppId(DPL::FromUTF8String(backupId), + DPL::FromUTF8String(deleteId)); + + if(!AceApi::registerAceWidgetFromDB(WidgetDAOReadOnly::getHandle( + DPL::FromUTF8String(deleteId)))) { + _E("ace database restore failed"); + } + } + + WidgetDAOReadOnly dao(DPL::FromUTF8String(deleteId)); + m_context.requestedPath = + DPL::ToUTF8String(*dao.getWidgetInstalledPath()); + } + Catch(WidgetDAOReadOnly::Exception::WidgetNotExist) + { + ThrowMsg(Exceptions::RecoveryFailed, "[WidgetNotExist] Failure in recovery db"); + } + Catch(WidgetDAO::Exception::DatabaseError) + { + ThrowMsg(Exceptions::RecoveryFailed, "[DatabaseError] Failure in recovery db"); + } +} + +void TaskRecovery::StartStep() +{ + LOGD("--------- : START ----------"); +} + +void TaskRecovery::EndStep() +{ + LOGD("--------- : END ----------"); +} +} //namespace RecoveryInstall +} //namespace Jobs diff --git a/src_wearable/jobs/widget_install/task_recovery.h b/src_wearable/jobs/widget_install/task_recovery.h new file mode 100644 index 0000000..92a9d79 --- /dev/null +++ b/src_wearable/jobs/widget_install/task_recovery.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file task_recovery.h + * @author soyoung kim (sy037.kim@samsung.com) + * @version 1.0 + */ + +#ifndef SRC_JOBS_WIDGET_INSTALL_TASK_RECOVERY_FILES_H_ +#define SRC_JOBS_WIDGET_INSTALL_TASK_RECOVERY_FILES_H_ + +#include +#include + +class InstallerContext; + +namespace Jobs { +namespace WidgetInstall { +class TaskRecovery : public DPL::TaskDecl +{ + private: + InstallerContext& m_context; + + void StartStep(); + void EndStep(); + void StepRecoveryDirectory(); + void StepRecoveryDatabase(); + + public: + explicit TaskRecovery(InstallerContext &context); +}; +} // namespace WidgetInstall +} // namespace Jobs +#endif /* SRC_JOBS_WIDGET_INSTALL_TASK_RECOVERY_FILES_H_ */ diff --git a/src_wearable/jobs/widget_install/task_remove_backup.cpp b/src_wearable/jobs/widget_install/task_remove_backup.cpp new file mode 100755 index 0000000..d691041 --- /dev/null +++ b/src_wearable/jobs/widget_install/task_remove_backup.cpp @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file task_remove_backup.cpp + * @author Soyoung kim(sy037.kim@samsung.com) + * @version 1.0 + * @brief Implementation file for installer task backup files remove + */ +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace WrtDB; + +namespace Jobs { +namespace WidgetInstall { +TaskRemoveBackupFiles::TaskRemoveBackupFiles(InstallerContext& context) : + DPL::TaskDecl(this), + m_context(context) +{ + AddStep(&TaskRemoveBackupFiles::StartStep); + if (m_context.mode.extension != InstallMode::ExtensionType::DIR) + { + AddStep(&TaskRemoveBackupFiles::StepRemoveBackupFiles); + } + AddStep(&TaskRemoveBackupFiles::StepDeleteBackupDB); + AddStep(&TaskRemoveBackupFiles::StepDeleteBackupWidgetInterfaceDB); + AddStep(&TaskRemoveBackupFiles::EndStep); +} + +void TaskRemoveBackupFiles::StepRemoveBackupFiles() +{ + std::ostringstream backupDir; + backupDir << m_context.locations->getBackupDir(); + + if (WrtUtilRemove(backupDir.str())) { + _D("Success to remove backup files : %s", backupDir.str().c_str()); + } else { + _E("Failed to remove backup directory : %s", backupDir.str().c_str()); + ThrowMsg(Exceptions::RemoveBackupFailed, + "Error occurs during removing existing folder"); + } + + std::string tmp = m_context.locations->getTemporaryPackageDir(); + if (WrtUtilRemove(tmp)) { + _D("Success to remove temp directory : %s", tmp.c_str()); + } else { + _E("Failed to remove temp directory : %s", tmp.c_str()); + } +} + +void TaskRemoveBackupFiles::StepDeleteBackupDB() +{ + _D("StepDeleteBackupDB"); + std::list idList = WidgetDAOReadOnly::getTzAppIdList(m_context.widgetConfig.tzPkgid); + FOREACH(it, idList){ + Try + { + DPL::String suffix = L".backup"; + if( it->size() >= suffix.size() && it->compare(it->size() - suffix.size() , suffix.size(), suffix) == 0) + WidgetDAO::unregisterWidget(*it); + } + Catch(WidgetDAOReadOnly::Exception::WidgetNotExist) + { + _E("Fail to delete old version db information"); + } + } +} + +void TaskRemoveBackupFiles::StepDeleteBackupWidgetInterfaceDB() +{ + _D("StepDeleteBackupWidgetInterfaceDB"); + using namespace WidgetInterfaceDB; + using namespace WrtDB; + + DbWidgetHandle handle = + WidgetDAOReadOnly::getHandle(m_context.widgetConfig.tzAppid); + std::string backupDbPath = WidgetInterfaceDAO::databaseFileName(handle); + backupDbPath += GlobalConfig::GetBackupDatabaseSuffix(); + + // remove backup database + if (remove(backupDbPath.c_str()) != 0) { + _W("Fail to remove"); + } +} + +void TaskRemoveBackupFiles::StartStep() +{ + LOGD("--------- : START ----------"); +} + +void TaskRemoveBackupFiles::EndStep() +{ + LOGD("--------- : END ----------"); +} +} //namespace WidgetInstall +} //namespace Jobs diff --git a/src_wearable/jobs/widget_install/task_remove_backup.h b/src_wearable/jobs/widget_install/task_remove_backup.h new file mode 100644 index 0000000..1dcdf5b --- /dev/null +++ b/src_wearable/jobs/widget_install/task_remove_backup.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file task_remove_backup.h + * @author Soyoung kim(sy037.kim@samsung.com) + * @version 1.0 + * @brief Header file for installer task backup files remove + */ +#ifndef INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_REMOVE_BACKUP_FILES_H +#define INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_REMOVE_BACKUP_FILES_H + +#include + +class InstallerContext; + +namespace Jobs { +namespace WidgetInstall { +class TaskRemoveBackupFiles : + public DPL::TaskDecl +{ + private: + InstallerContext& m_context; + + void StepRemoveBackupFiles(); + void StepDeleteBackupDB(); + void StepDeleteBackupWidgetInterfaceDB(); + + void StartStep(); + void EndStep(); + + public: + TaskRemoveBackupFiles(InstallerContext& context); +}; +} //namespace WidgetInstall +} //namespace Jobs + +#endif // INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_REMOVE_BACKUP_FILES_H diff --git a/src_wearable/jobs/widget_install/task_smack.cpp b/src_wearable/jobs/widget_install/task_smack.cpp new file mode 100644 index 0000000..5076d14 --- /dev/null +++ b/src_wearable/jobs/widget_install/task_smack.cpp @@ -0,0 +1,320 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file task_smack.cpp + * @author Piotr Kozbial (p.kozbial@samsung.com) + * @version 1.0 + * @brief Implementation file for installer task smack + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace WrtDB; +using namespace ValidationCore; + +namespace { +const int MAX_BUF_SIZE = 128; +void freeList(const char** list) { + for (int i = 0; list[i] != NULL; i++) + { + delete(list[i]); + } + delete[] list; +} +} + +namespace Jobs { +namespace WidgetInstall { +TaskSmack::TaskSmack(InstallerContext& context) : + DPL::TaskDecl(this), + m_context(context) +{ + AddStep(&TaskSmack::StartStep); + AddStep(&TaskSmack::StepSetInstall); + AddStep(&TaskSmack::StepSmackFolderLabeling); + AddStep(&TaskSmack::StepSmackPrivilege); + AddStep(&TaskSmack::StepAddLabelNPRuntime); + AddStep(&TaskSmack::StepLabelSignatureFiles); + AddStep(&TaskSmack::EndStep); + + AddAbortStep(&TaskSmack::StepAbortSmack); +} + +void TaskSmack::StepSetInstall() +{ + _D("----------------> SMACK: StepStartSetSmack()"); + + m_pkgId = DPL::ToUTF8String(m_context.widgetConfig.tzPkgid); + + if (PC_OPERATION_SUCCESS != perm_app_install(m_pkgId.c_str())) { + ThrowMsg(Exceptions::NotAllowed, "Instalation failure. " + "failure in creating smack rules file."); + } +} + +void TaskSmack::StepSmackFolderLabeling() +{ + _D("----------------> SMACK:\ + Jobs::WidgetInstall::TaskSmack::SmackFolderLabelingStep()"); + + /* /opt/usr/apps/[pkgid] directory's label is "_" */ + if (PC_OPERATION_SUCCESS != perm_app_setup_path(m_pkgId.c_str(), + m_context.locations->getPackageInstallationDir().c_str(), + APP_PATH_ANY_LABEL, "_")) { + _W("Add label to %s", m_context.locations->getPackageInstallationDir().c_str()); + } + + /* for prelaod */ + if (m_context.mode.installTime == InstallMode::InstallTime::PRELOAD) { + if (PC_OPERATION_SUCCESS != perm_app_setup_path(m_pkgId.c_str(), + m_context.locations->getUserDataRootDir().c_str(), + APP_PATH_ANY_LABEL, "_")) { + } + } + + /* res directory */ + std::string resDir = m_context.locations->getPackageInstallationDir() + + "/res"; + + if (PC_OPERATION_SUCCESS != perm_app_setup_path(m_pkgId.c_str(), resDir.c_str(), + APP_PATH_PRIVATE)) { + _W("Add label to %s", resDir.c_str()); + } + + /* data directory */ + if (PC_OPERATION_SUCCESS != perm_app_setup_path(m_pkgId.c_str(), + m_context.locations->getPrivateStorageDir().c_str(), + APP_PATH_PRIVATE)) { + _W("Add label to %s", m_context.locations->getPrivateStorageDir().c_str()); + } + + /* tmp directory */ + if (PC_OPERATION_SUCCESS != perm_app_setup_path(m_pkgId.c_str(), + m_context.locations->getPrivateTempStorageDir().c_str(), + APP_PATH_PRIVATE)) + { + _W("Add label to %s", m_context.locations->getPrivateTempStorageDir().c_str()); + } + + /* bin directory */ + if (PC_OPERATION_SUCCESS != perm_app_setup_path(m_pkgId.c_str(), + m_context.locations->getBinaryDir().c_str(), + APP_PATH_PRIVATE)) { + _W("Add label to %s", m_context.locations->getBinaryDir().c_str()); + } + + if(!setLabelForSharedDir(m_pkgId.c_str())) { + _W("Add label to shared directory"); + } + + /* TODO : set label at wrt-client */ +} + +void TaskSmack::StepSmackPrivilege() +{ + _D("----------------> SMACK:\ + Jobs::WidgetInstall::TaskSmack::SmackPrivilegeStep()"); + + std::string id = DPL::ToUTF8String(m_context.widgetConfig.tzPkgid); + char* appId = NULL; + appId = (char*)calloc(1, id.length() + 1); + snprintf(appId, id.length() + 1, "%s", id.c_str()); + + WrtDB::ConfigParserData::PrivilegeList privileges = + m_context.widgetConfig.configInfo.privilegeList; + + char** perm_list = new char*[privileges.size() + 1]; + int index = 0; + FOREACH(it, privileges) { + _D("Permission : %ls", it->name.c_str()); + int length = DPL::ToUTF8String(it->name).length(); + char *priv = new char[length + 1]; + snprintf(priv, length + 1, "%s", + DPL::ToUTF8String(it->name).c_str()); + perm_list[index++] = priv; + } + perm_list[index] = NULL; + + if (PC_OPERATION_SUCCESS != perm_app_enable_permissions(appId, APP_TYPE_WGT, + const_cast(perm_list), true)) { + _W("failure in contructing smack rules based on perm_list"); + } + + free(appId); + index = 0; + while (NULL != perm_list[index]) { + delete [] perm_list[index++]; + } + delete [] perm_list; + + m_context.job->UpdateProgress( + InstallerContext::INSTALL_SMACK_ENABLE, + "Widget SMACK Enabled"); +} + +void TaskSmack::StepAddLabelNPRuntime() +{ + _D("----------------> SMACK:\ + Jobs::WidgetInstall::TaskSmack::StepAddLabelNPRuntime()"); + + if (0 == access(m_context.locations->getNPPluginsDir().c_str(), F_OK)) { + if (PC_OPERATION_SUCCESS != + perm_app_setup_path(DPL::ToUTF8String(m_context.widgetConfig.tzPkgid).c_str(), + m_context.locations->getNPPluginsExecFile().c_str(), + PERM_APP_PATH_NPRUNTIME)) { + _E("failed to set smack execute label to %s", + m_context.locations->getNPPluginsExecFile().c_str()); + } + } +} + + +void TaskSmack::StepLabelSignatureFiles() +{ + _D("----------------> SMACK:\ + Jobs::WidgetInstall::TaskSmack::StepLabelSignatureFiles()"); + + DPL::Utils::Path widgetPath{ + m_context.locations->getPackageInstallationDir()}; + widgetPath /= WrtDB::GlobalConfig::GetWidgetSrcPath(); + + SignatureFileInfoSet signatureFiles; + SignatureFinder signatureFinder(widgetPath.Fullpath()); + if (SignatureFinder::NO_ERROR != signatureFinder.find(signatureFiles)) { + ThrowMsg(Exceptions::SignatureNotFound, + "Error while discovering signature files."); + } + + for (auto it = signatureFiles.cbegin(); it != signatureFiles.cend(); ++it) { + auto sigPath = widgetPath / it->getFileName(); + + _D("Setting label to %s", sigPath.Fullpath().c_str()); + if (PC_OPERATION_SUCCESS != perm_app_setup_path(m_pkgId.c_str(), + sigPath.Fullpath().c_str(), + APP_PATH_ANY_LABEL, "_")) { + _W("Failed to set label to %s", sigPath.Fullpath().c_str()); + } + } +} + +void TaskSmack::StepRevokeForUpdate() +{ + _D("----------------> SMACK:\ + Jobs::WidgetInstall::TaskSmack::StepRevokePrivilegeForUpdate()"); + + if (PC_OPERATION_SUCCESS != perm_app_revoke_permissions(m_pkgId.c_str())) { + _W("failure in revoking smack permissions"); + } +} + +void TaskSmack::StepAbortSmack() +{ + _D("----------------> SMACK:\ + Jobs::WidgetInstall::TaskSmack::StepAbortSmack()"); + + if (PC_OPERATION_SUCCESS != perm_app_revoke_permissions(m_pkgId.c_str())) { + _W("failure in revoking smack permissions"); + } + + if (PC_OPERATION_SUCCESS != perm_app_uninstall(m_pkgId.c_str())) { + _W("failure in removing smack rules file"); + } +} + +bool TaskSmack::setLabelForSharedDir(const char* pkgId) +{ + /* /shared directory */ + if (PC_OPERATION_SUCCESS != perm_app_setup_path(pkgId, + m_context.locations->getSharedRootDir().c_str(), + APP_PATH_ANY_LABEL, "_")) { + _W("Add label to %s", m_context.locations->getUserDataRootDir().c_str()); + } + + /* /shared/res directory */ + if (PC_OPERATION_SUCCESS != perm_app_setup_path(pkgId, + m_context.locations->getSharedResourceDir().c_str(), + APP_PATH_ANY_LABEL, "_")) { + _W("Add label to %s", m_context.locations->getSharedResourceDir().c_str()); + } + + /* /shared/trusted directory */ + CertificatePtr rootCert = m_context.widgetSecurity.getAuthorCertificatePtr(); + if (!!rootCert) { + ValidationCore::Crypto::Hash::SHA1 sha1; + sha1.Append(rootCert->getDER()); + sha1.Finish(); + std::string sha1String = sha1.ToBase64String(); + size_t iPos = sha1String.find("/"); + while(iPos < std::string::npos) { + sha1String.replace(iPos, 1, "#"); + iPos = sha1String.find("/"); + } + + _D("sha1 label string : %s", sha1String.c_str()); + + if (PC_OPERATION_SUCCESS != perm_app_setup_path(pkgId, + m_context.locations->getSharedTrustedDir().c_str(), + APP_PATH_GROUP_RW, sha1String.c_str())) { + _W("Add label to %s", m_context.locations->getBinaryDir().c_str()); + } + } + + /* /shared/data directory */ + if (PC_OPERATION_SUCCESS != perm_app_setup_path(pkgId, + m_context.locations->getSharedDataDir().c_str(), + APP_PATH_PUBLIC_RO)) { + _W("Add label to %s", m_context.locations->getSharedDataDir().c_str()); + } + + return true; +} + +void TaskSmack::StartStep() +{ + LOGD("--------- : START ----------"); + if (PC_OPERATION_SUCCESS != perm_begin()) { + LOGE("Failed to smack transaction begin."); + ThrowMsg(Exceptions::SmackTransactionFailed, "Failed to smack transaction begin"); + } +} + +void TaskSmack::EndStep() +{ + LOGD("--------- : END ----------"); + if (PC_OPERATION_SUCCESS != perm_end()) { + LOGE("Failed to smack transaction end."); + ThrowMsg(Exceptions::SmackTransactionFailed, "Failed to smack transaction end"); + } +} +} //namespace WidgetInstall +} //namespace Jobs diff --git a/src_wearable/jobs/widget_install/task_smack.h b/src_wearable/jobs/widget_install/task_smack.h new file mode 100644 index 0000000..2c7b54f --- /dev/null +++ b/src_wearable/jobs/widget_install/task_smack.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file task_smack.h + * @author Piotr Kozbial (p.kozbial@samsung.com) + * @version 1.0 + * @brief Header file for installer task smack + */ +#ifndef INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_SMACK_H +#define INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_SMACK_H + +#include + +class InstallerContext; + +namespace Jobs { +namespace WidgetInstall { +class TaskSmack : + public DPL::TaskDecl +{ + private: + InstallerContext& m_context; + std::string m_pkgId; + + void StepSetInstall(); + void StepSmackFolderLabeling(); + void StepSmackPrivilege(); + void StepAddLabelNPRuntime(); + void StepLabelSignatureFiles(); + void StepRevokeForUpdate(); + void StepAbortSmack(); + + bool setLabelForSharedDir(const char* pkgId); + + void StartStep(); + void EndStep(); + + public: + TaskSmack(InstallerContext& context); +}; +} //namespace WidgetInstall +} //namespace Jobs + +#endif /* INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_SMACK_H */ diff --git a/src_wearable/jobs/widget_install/task_status_check.cpp b/src_wearable/jobs/widget_install/task_status_check.cpp new file mode 100644 index 0000000..6a60cff --- /dev/null +++ b/src_wearable/jobs/widget_install/task_status_check.cpp @@ -0,0 +1,159 @@ + /* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file task_status_check.cpp + * @author Soyoung Kim (sy037.kim@samsung.com) + * @version 1.0 + * @brief Implementation file for installer task install osp service + */ +#include "task_status_check.h" + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include + +namespace Jobs { +namespace WidgetInstall { +TaskStatusCheck::TaskStatusCheck(InstallerContext& context) : + DPL::TaskDecl(this), + m_context(context) +{ + AddStep(&TaskStatusCheck::StartStep); + AddStep(&TaskStatusCheck::CheckAppRunningStateStep); + AddStep(&TaskStatusCheck::DynamicBoxesRemoveStep); + AddStep(&TaskStatusCheck::EndStep); +} + +void TaskStatusCheck::CheckAppRunningStateStep() +{ + _D("Step: CheckAppRunningStateStep"); + std::string webAppPkgId = DPL::ToUTF8String(m_context.widgetConfig.tzPkgid); + + int ret = 0; + pkgmgrinfo_pkginfo_h handle; + ret = pkgmgrinfo_pkginfo_get_pkginfo(webAppPkgId.c_str(), &handle); + if (ret != PMINFO_R_OK) { + _E("Can't find [%s] in package manager", webAppPkgId.c_str()); + ThrowMsg(Jobs::WidgetInstall::Exceptions::GetInfoPkgMgrFailed, + "package id can't find from package manager"); + } + ret = pkgmgrinfo_appinfo_get_list(handle, PMINFO_ALL_APP, + terminateRunningApp, NULL); + if (ret != PMINFO_R_OK) { + pkgmgrinfo_pkginfo_destroy_pkginfo(handle); + ThrowMsg(Jobs::WidgetInstall::Exceptions::WidgetRunningError, + "widget is running"); + } + pkgmgrinfo_pkginfo_destroy_pkginfo(handle); +} + +int TaskStatusCheck::terminateRunningApp(pkgmgrinfo_appinfo_h handle, + void* /*user_data*/) +{ + char *appId = NULL; + pkgmgrinfo_appinfo_get_appid(handle, &appId); + _D("# Terminating App : [%s]", appId); + + bool isRunning = false; + int ret = app_manager_is_running(appId, &isRunning); + if (APP_MANAGER_ERROR_NONE != ret) { + _E("Fail to get running state"); + ThrowMsg(Jobs::WidgetInstall::Exceptions::WidgetRunningError, + "widget is running"); + } + + if (true == isRunning) { + // get app_context for running application + // app_context must be released with app_context_destroy + app_context_h appCtx = NULL; + ret = + app_manager_get_app_context(appId, &appCtx); + if (APP_MANAGER_ERROR_NONE != ret) { + _E("Fail to get app_context"); + ThrowMsg(Jobs::WidgetInstall::Exceptions::WidgetRunningError, + "widget is running"); + } + + // terminate app_context_h + ret = app_manager_terminate_app(appCtx); + if (APP_MANAGER_ERROR_NONE != ret) { + _E("Fail to terminate running application"); + app_context_destroy(appCtx); + ThrowMsg(Jobs::WidgetInstall::Exceptions::WidgetRunningError, + "widget is running"); + } else { + app_context_destroy(appCtx); + // app_manager_terminate_app isn't sync API + // wait until application isn't running (50ms * 100) + bool isStillRunning = true; + int checkingloop = 100; + struct timespec duration = { 0, 50 * 1000 * 1000 }; + while (--checkingloop >= 0) { + nanosleep(&duration, NULL); + int ret = app_manager_is_running(appId, + &isStillRunning); + if (APP_MANAGER_ERROR_NONE != ret) { + _E("Fail to get running state"); + ThrowMsg(Jobs::WidgetInstall::Exceptions::WidgetRunningError, + "widget is running"); + } + if (!isStillRunning) { + break; + } + } + if (isStillRunning) { + _E("Fail to terminate running application"); + ThrowMsg(Jobs::WidgetInstall::Exceptions::WidgetRunningError, + "widget is running"); + } + _D("terminate application"); + } + } + return 0; +} + +void TaskStatusCheck::DynamicBoxesRemoveStep() +{ + _D("Step: DynamicBoxesRemoveStep"); + + // check if this webapp has dynaimc boxes, and request to remove them + web_provider_service_wait_boxes_removed( + DPL::ToUTF8String(m_context.widgetConfig.tzAppid).c_str()); + + _D("Finished to handle this web app's dynamic box"); +} + +void TaskStatusCheck::StartStep() +{ + LOGD("--------- : START ----------"); +} + +void TaskStatusCheck::EndStep() +{ + LOGD("--------- : END ----------"); +} +} //namespace WidgetInstall +} //namespace Jobs diff --git a/src_wearable/jobs/widget_install/task_status_check.h b/src_wearable/jobs/widget_install/task_status_check.h new file mode 100644 index 0000000..3ae5a95 --- /dev/null +++ b/src_wearable/jobs/widget_install/task_status_check.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file task_status_check.h + * @author soyoung kim (sy037.kim@samsung.com) + * @version 1.0 + */ + +#ifndef SRC_JOBS_WIDGET_INSTALL_TASK_STATUS_CHECK_H_ +#define SRC_JOBS_WIDGET_INSTALL_TASK_STATUS_CHECK_H_ + +#include +#include +#include + +class InstallerContext; + +namespace Jobs { +namespace WidgetInstall { +class TaskStatusCheck : public DPL::TaskDecl +{ + private: + // Installation context + InstallerContext &m_context; + + void CheckAppRunningStateStep(); + void DynamicBoxesRemoveStep(); + + void StartStep(); + void EndStep(); + + static int terminateRunningApp(pkgmgrinfo_appinfo_h handle, void *user_data); + + public: + explicit TaskStatusCheck(InstallerContext &installerContext); +}; +} // namespace WidgetInstall +} // namespace Jobs +#endif /* SRC_JOBS_WIDGET_INSTALL_TASK_STATUS_CHECK_H_ */ diff --git a/src_wearable/jobs/widget_install/task_update_files.cpp b/src_wearable/jobs/widget_install/task_update_files.cpp new file mode 100644 index 0000000..95d5d96 --- /dev/null +++ b/src_wearable/jobs/widget_install/task_update_files.cpp @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file task_update_files.cpp + * @author Soyoung Kim (sy037.kim@samsung.com) + * @version 1.0 + * @brief Implementation file for installer task update files + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace WrtDB; + +namespace { +inline const char* GetWidgetBackupDirPath() +{ + return "backup"; +} +} + +namespace Jobs { +namespace WidgetInstall { +TaskUpdateFiles::TaskUpdateFiles(InstallerContext& context) : + DPL::TaskDecl(this), + m_context(context) +{ + AddStep(&TaskUpdateFiles::StartStep); + AddStep(&TaskUpdateFiles::StepBackupDirectory); + AddStep(&TaskUpdateFiles::EndStep); + + AddAbortStep(&TaskUpdateFiles::StepAbortBackupDirectory); +} + +void TaskUpdateFiles::StepBackupDirectory() +{ + _D("StepCreateBackupFolder"); + + Try { + std::string pkgid = + DPL::ToUTF8String(m_context.widgetConfig.tzPkgid); + if (APP2EXT_SD_CARD == app2ext_get_app_location(pkgid.c_str())) { + _D("Installed external directory"); + WidgetInstallToExtSingleton::Instance().initialize(pkgid); + WidgetInstallToExtSingleton::Instance().disable(); + } + } Catch(WidgetInstallToExt::Exception::ErrorInstallToExt) { + _E("Failed disable app2sd"); + ReThrowMsg(Exceptions::BackupFailed, "Error occurs during disable app2sd"); + } + + std::string backPath = m_context.locations->getBackupDir(); + _D("Backup resource directory path : %s", backPath.c_str()); + std::string pkgPath = m_context.locations->getPackageInstallationDir(); + + if (0 == access(backPath.c_str(), F_OK)) { + if (!WrtUtilRemove(backPath)) { + ThrowMsg(Exceptions::RemovingFolderFailure, + "Error occurs during removing backup resource directory"); + } + } + _D("copy : %s to %s", pkgPath.c_str(), backPath.c_str()); + if ((rename(pkgPath.c_str(), backPath.c_str())) != 0) { + _E("Failed to rename %s to %s", pkgPath.c_str(), backPath.c_str()); + ThrowMsg(Exceptions::BackupFailed, + "Error occurs during rename file"); + } + + WrtUtilMakeDir(pkgPath); +} + +void TaskUpdateFiles::StepAbortBackupDirectory() +{ + _D("StepAbortCopyFiles"); + + std::string backPath = m_context.locations->getBackupDir(); + std::string pkgPath = m_context.locations->getPackageInstallationDir(); + + _D("Backup Folder %s to %s", backPath.c_str(), pkgPath.c_str()); + + if (!WrtUtilRemove(pkgPath)) { + _E("Failed to remove %s", pkgPath.c_str()); + } + + if (rename(backPath.c_str(), pkgPath.c_str()) != 0) { + _E("Failed to rename %s to %s", backPath.c_str(), pkgPath.c_str()); + } +} + +void TaskUpdateFiles::StartStep() +{ + LOGD("--------- : START ----------"); +} + +void TaskUpdateFiles::EndStep() +{ + m_context.job->UpdateProgress( + InstallerContext::INSTALL_CREATE_BACKUP_DIR, + "Backup directory created for update"); + + LOGD("--------- : END ----------"); +} +} //namespace WidgetInstall +} //namespace Jobs diff --git a/src_wearable/jobs/widget_install/task_update_files.h b/src_wearable/jobs/widget_install/task_update_files.h new file mode 100644 index 0000000..1d02e0e --- /dev/null +++ b/src_wearable/jobs/widget_install/task_update_files.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file task_update_files.h + * @author Soyoung Kim (sy037.kim@samsung.com) + * @version 1.0 + * @brief Header file for installer task update files + */ +#ifndef INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_UPDATE_FILES_H +#define INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_UPDATE_FILES_H + +#include +#include +#include + +class InstallerContext; + +namespace { +typedef std::set ExistFileList; +} + +namespace Jobs { +namespace WidgetInstall { +class TaskUpdateFiles : + public DPL::TaskDecl +{ + private: + InstallerContext& m_context; + + void StepBackupDirectory(); + + void StepAbortBackupDirectory(); + + void StartStep(); + void EndStep(); + + public: + TaskUpdateFiles(InstallerContext& context); +}; +} //namespace WidgetInstall +} //namespace Jobs + +#endif /* INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_UPDATE_FILES_H */ diff --git a/src_wearable/jobs/widget_install/task_user_data_manipulation.cpp b/src_wearable/jobs/widget_install/task_user_data_manipulation.cpp new file mode 100644 index 0000000..43f29c3 --- /dev/null +++ b/src_wearable/jobs/widget_install/task_user_data_manipulation.cpp @@ -0,0 +1,274 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file task_user_data_manipulation.cpp + * @author Soyoung Kim (sy037.kim@samsung.com) + * @version 1.0 + * @brief Implementation file for installer task user data folder + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define WEBAPP_DEFAULT_UID 5000 +#define WEBAPP_DEFAULT_GID 5000 + +namespace { +const mode_t PRIVATE_STORAGE_MODE = 0700; +const mode_t SHARED_STORAGE_MODE = 0755; +} + +using namespace WrtDB; + +namespace { +void changeOwnerForDirectory(std::string storagePath, mode_t mode) { + if (euidaccess(storagePath.c_str(), F_OK) != 0) { + if (!WrtUtilMakeDir(storagePath, mode)) { + _E("Failed to create directory : %s", storagePath.c_str()); + ThrowMsg(Jobs::WidgetInstall::Exceptions::FileOperationFailed, + "Failed to create directory : " << storagePath); + } + // '5000' is default uid, gid for applications. + // So installed applications should be launched as process of uid + // '5000'. + // the process can access private directory 'data' of itself. + if (chown(storagePath.c_str(), + WEBAPP_DEFAULT_UID, + WEBAPP_DEFAULT_GID) != 0) + { + ThrowMsg(Jobs::WidgetInstall::Exceptions::FileOperationFailed, + "Chown to invaild user"); + } + } else if (euidaccess(storagePath.c_str(), W_OK | R_OK | X_OK) == 0) { + _D("%s already exists.", storagePath.c_str()); + // Even if private directory already is created, private dircetory + // should change owner (recursively). + if (chown(storagePath.c_str(), + WEBAPP_DEFAULT_UID, + WEBAPP_DEFAULT_GID) != 0) + { + ThrowMsg(Jobs::WidgetInstall::Exceptions::FileOperationFailed, + "Chown to invaild user"); + } + if (chmod(storagePath.c_str(), mode) != 0) { + ThrowMsg(Jobs::WidgetInstall::Exceptions::FileOperationFailed, + "chmod to 0700"); + } + } else { + ThrowMsg(Jobs::WidgetInstall::Exceptions::FileOperationFailed, + "No access to private storage."); + } +} +} + +namespace Jobs { +namespace WidgetInstall { +TaskUserDataManipulation::TaskUserDataManipulation(InstallerContext& context) : + DPL::TaskDecl(this), + m_context(context) +{ + AddStep(&TaskUserDataManipulation::StartStep); + AddStep(&TaskUserDataManipulation::StepCreatePrivateStorageDir); + AddStep(&TaskUserDataManipulation::StepCreateSharedFolder); + AddStep(&TaskUserDataManipulation::StepLinkForPreload); + AddStep(&TaskUserDataManipulation::EndStep); +} + +void TaskUserDataManipulation::StepCreatePrivateStorageDir() +{ + + if (m_context.mode.installTime == InstallMode::InstallTime::FOTA + && m_context.isUpdateMode) + { + return; + } + + if (m_context.mode.installTime == InstallMode::InstallTime::PRELOAD + || m_context.mode.installTime == InstallMode::InstallTime::FOTA) { + std::string userWidgetDir = m_context.locations->getUserDataRootDir(); + _D("Create user data directory : %s", userWidgetDir.c_str()); + WrtUtilMakeDir(userWidgetDir); + } + std::string storagePath = m_context.locations->getPrivateStorageDir(); + _D("Create private storage directory : %s", m_context.locations->getPrivateStorageDir().c_str()); + + changeOwnerForDirectory(storagePath, PRIVATE_STORAGE_MODE); + + if (m_context.isUpdateMode) { //update + std::string backData = m_context.locations->getBackupPrivateDir(); + _D("copy private storage %s to %s", backData.c_str(), storagePath.c_str()); + if (!DirectoryApi::DirectoryCopy(backData, storagePath)) { + _E("Failed to rename %s to %s", backData.c_str(), storagePath.c_str()); + ThrowMsg(Exceptions::BackupFailed, + "Error occurs copy private strage files"); + } + } + + std::string tempStoragePath = m_context.locations->getPrivateTempStorageDir(); + _D("Create temp private storage directory : %s", tempStoragePath.c_str()); + changeOwnerForDirectory(tempStoragePath, PRIVATE_STORAGE_MODE); + + m_context.job->UpdateProgress( + InstallerContext::INSTALL_CREATE_PRIVATE_STORAGE, + "Create private storage for user"); +} + +void TaskUserDataManipulation::StepLinkForPreload() +{ + if (m_context.mode.rootPath == InstallMode::RootPath::RO) { + std::string optRes = m_context.locations->getUserDataRootDir() + + WrtDB::GlobalConfig::GetWidgetResPath(); + std::string usrRes = m_context.locations->getPackageInstallationDir() + + WrtDB::GlobalConfig::GetWidgetResPath(); + + std::string oldRes = optRes + ".old"; + + // Rename path if already exist. + if (0 == access(optRes.c_str(), F_OK)) { + if (-1 == rename(optRes.c_str(), oldRes.c_str())) { + _E("Failed To rename %s -> %s", optRes.c_str(), oldRes.c_str()); + } + } + + if (0 != access(optRes.c_str(), F_OK)) { + _D("Make symbolic name for preload app %s to %s", usrRes.c_str(), optRes.c_str()); + + if (symlink(usrRes.c_str(), optRes.c_str()) != 0) + { + int error = errno; + if (error) + _E("Failed to make a symbolic name for a file [%s]", (DPL::GetErrnoString(error)).c_str()); + ThrowMsg(Exceptions::FileOperationFailed, + "Symbolic link creating is not done."); + } + } + + /* link for data directory */ + std::string storagePath = m_context.locations->getPrivateStorageDir(); + std::string dataDir = m_context.locations->getPackageInstallationDir() + + "/" + WrtDB::GlobalConfig::GetWidgetPrivateStoragePath(); + if (0 != access(dataDir.c_str(), F_OK)) { + _D("Make symbolic name for preload app %s to %s", storagePath.c_str(), dataDir.c_str()); + + if (symlink(storagePath.c_str(), dataDir.c_str()) != 0) + { + int error = errno; + if (error) + _E("Failed to make a symbolic name for a file [%s]", (DPL::GetErrnoString(error)).c_str()); + ThrowMsg(Exceptions::FileOperationFailed, + "Symbolic link creating is not done."); + } + changeOwnerForDirectory(dataDir, PRIVATE_STORAGE_MODE); + } + + if (m_context.widgetConfig.packagingType != PKG_TYPE_HYBRID_WEB_APP) { + std::string widgetBinPath = m_context.locations->getBinaryDir(); + std::string userBinPath = m_context.locations->getUserBinaryDir(); + std::string oldBinPath = userBinPath + ".old"; + + // Rename path if already exist. + if (0 == access(userBinPath.c_str(), F_OK)) { + if (-1 == rename(userBinPath.c_str(), oldBinPath.c_str())) { + _E("Failed To rename %s -> %s", userBinPath.c_str(), oldBinPath.c_str()); + } + } + + _D("Make symbolic link for preload app %s to %s", widgetBinPath.c_str(), userBinPath.c_str()); + if (symlink(widgetBinPath.c_str(), userBinPath.c_str()) != 0) + { + int error = errno; + if (error) + _E("Failed to make a symbolic name for a file [%s]", (DPL::GetErrnoString(error)).c_str()); + ThrowMsg(Exceptions::FileOperationFailed, + "Symbolic link creating is not done."); + } + + } + } +} + +void TaskUserDataManipulation::StepCreateSharedFolder() +{ + if (m_context.mode.installTime == InstallMode::InstallTime::FOTA + && m_context.isUpdateMode) + { + return; + } + + _D("StepCreateSharedFolder"); + std::string sharedPath = m_context.locations->getSharedRootDir(); + _D("Create shared directory : %s", m_context.locations->getSharedRootDir().c_str()); + + WrtUtilMakeDir(sharedPath); + WrtUtilMakeDir(m_context.locations->getSharedResourceDir()); + + changeOwnerForDirectory(m_context.locations->getSharedDataDir(), + SHARED_STORAGE_MODE); + changeOwnerForDirectory(m_context.locations->getSharedTrustedDir(), + SHARED_STORAGE_MODE); + + + // additional check for rootPath installation + // If this app is preloaded, "shared" diretory is already on place and do not needs to be moved + // TODO: why "shared" is on RW partion always but "data" and "tmp" are linked + if (m_context.isUpdateMode + && !(m_context.mode.rootPath == InstallMode::RootPath::RO + && m_context.mode.installTime == InstallMode::InstallTime::PRELOAD)) { + + /* Restore /shared/data */ + _D("copy %s to %s", m_context.locations->getBackupSharedDataDir().c_str(), m_context.locations->getSharedDataDir().c_str()); + if (!DirectoryApi::DirectoryCopy( + m_context.locations->getBackupSharedDataDir(), + m_context.locations->getSharedDataDir())) { + _E("Failed to rename %s to %s", m_context.locations->getBackupSharedDataDir().c_str(), m_context.locations->getSharedDataDir().c_str()); + ThrowMsg(Exceptions::BackupFailed, + "Error occurs copy shared strage files"); + } + + /* Restore /shared/trusted */ + _D("copy %s to %s", m_context.locations->getBackupSharedTrustedDir().c_str(), m_context.locations->getSharedTrustedDir().c_str()); + if (!DirectoryApi::DirectoryCopy( + m_context.locations->getBackupSharedTrustedDir(), + m_context.locations->getSharedTrustedDir())) { + _E("Failed to rename %s to %s", m_context.locations->getBackupSharedTrustedDir().c_str(), m_context.locations->getSharedTrustedDir().c_str()); + ThrowMsg(Exceptions::BackupFailed, + "Error occurs copy shared strage files"); + } + } +} + +void TaskUserDataManipulation::StartStep() +{ + LOGD("--------- : START ----------"); +} + +void TaskUserDataManipulation::EndStep() +{ + LOGD("--------- : END ----------"); +} +} //namespace WidgetInstall +} //namespace Jobs diff --git a/src_wearable/jobs/widget_install/task_user_data_manipulation.h b/src_wearable/jobs/widget_install/task_user_data_manipulation.h new file mode 100644 index 0000000..fbfabcc --- /dev/null +++ b/src_wearable/jobs/widget_install/task_user_data_manipulation.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file task_user_data_manipulation.cpp + * @author Soyoung Kim (sy037.kim@samsung.com) + * @version 1.0 + * @brief Implementation file for installer task user data folder + */ +#ifndef JOS_WIDGET_INSTALL_TASK_USER_DATA_MANIPULATION_H +#define JOS_WIDGET_INSTALL_TASK_USER_DATA_MANIPULATION_H + +#include + +class InstallerContext; + +namespace Jobs { +namespace WidgetInstall { +class TaskUserDataManipulation : + public DPL::TaskDecl +{ + InstallerContext& m_context; + + void StartStep(); + void EndStep(); + void StepCreatePrivateStorageDir(); + void StepCreateSharedFolder(); + void StepLinkForPreload(); + + public: + TaskUserDataManipulation(InstallerContext& context); +}; +} //namespace WidgetInstall +} //namespace Jobs + +#endif //JOS_WIDGET_INSTALL_TASK_USER_DATA_MANIPULATION_H diff --git a/src_wearable/jobs/widget_install/view_mode.h b/src_wearable/jobs/widget_install/view_mode.h new file mode 100644 index 0000000..a4acc39 --- /dev/null +++ b/src_wearable/jobs/widget_install/view_mode.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file view_mode.h + * @author Krzysztof Jackiewicz (k.jackiewicz@samsung.com) + * @version 1.0 + */ + +#ifndef SRC_JOBS_WIDGET_INSTALL_VIEW_MODE_H_ +#define SRC_JOBS_WIDGET_INSTALL_VIEW_MODE_H_ + +namespace Jobs { +namespace WidgetInstall { +enum ViewMode +{ + WINDOWED = 0, + FLOATING, + FULLSCREEN, + MAXIMIZED, + MINIMIZED +}; +} // WidgetInstall +} // Jobs + +#endif /* SRC_JOBS_WIDGET_INSTALL_VIEW_MODE_H_ */ diff --git a/src_wearable/jobs/widget_install/widget_install_context.h b/src_wearable/jobs/widget_install/widget_install_context.h new file mode 100644 index 0000000..1e7e86d --- /dev/null +++ b/src_wearable/jobs/widget_install/widget_install_context.h @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file installer_structs.h + * @author Pawel Sikorski (p.sikorski@samgsung.com) + * @version + * @brief Definition file of installer tasks data structures + */ +#ifndef INSTALLER_CONTEXT_H +#define INSTALLER_CONTEXT_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Jobs { +namespace WidgetInstall { +class JobWidgetInstall; +} //namespace Jobs +} //namespace WidgetInstall + +class WidgetModel; + +typedef std::map RequestedDevCapsMap; + +struct InstallerContext +{ + typedef enum InstallStepEnum + { + INSTALL_START = 0, + INSTALL_PARSE_CONFIG, + INSTALL_CHECK_FILE, + + INSTALL_RDS_DELTA_CHECK, + INSTALL_RDS_PREPARE, + + INSTALL_CREATE_BACKUP_DIR, /* For Update */ + INSTALL_DIR_CREATE, + INSTALL_UNZIP_WGT, + INSTALL_WIDGET_CONFIG1, + INSTALL_WIDGET_CONFIG2, + INSTALL_DIGSIG_CHECK, + INSTALL_CERT_CHECK, + INSTALL_CERTIFY_LEVEL_CHECK, + INSTALL_CREATE_PRIVATE_STORAGE, + INSTALL_BACKUP_ICONFILE, /* For Update */ + INSTALL_COPY_ICONFILE, + INSTALL_COPY_LIVEBOX_FILES, + INSTALL_CREATE_EXECFILE, + INSTALL_CREATE_MANIFEST, + INSTALL_ECRYPTION_FILES, + INSTALL_INSTALL_OSPSVC, + INSTALL_NEW_DB_INSERT, + INSTALL_ACE_PREPARE, + INSTALL_ACE_CHECK, + INSTALL_SMACK_ENABLE, + INSTALL_PKGINFO_UPDATE, + INSTALL_SET_CERTINFO, + + INSTALL_END + } InstallStep; + + // Installation state variables + WrtDB::WidgetRegisterInfo widgetConfig; ///< WidgetConfigInfo + boost::optional locations; + Jobs::WidgetInstall::WidgetSecurity widgetSecurity; ///< Widget Domain + // information. + InstallStep installStep; ///< current step of installation + Jobs::WidgetInstall::JobWidgetInstall *job; + ///< Whether this is an update or normal installation + Jobs::WidgetInstall::FeatureLogicPtr featureLogic; + /** List of dev-caps that are requested in widget config file. + * Additional flag tells whether dev cap gets "static" permission + * (will always have PERMIT from ACE Policy). They will therefore receive + * static SMACK permission. (They may be forbidden because + * of ACE User Settings, but for now we do not protect this + * case with SMACK). */ + RequestedDevCapsMap staticPermittedDevCaps; + std::string installInfo; /// + InstallLocationType locationType; + bool isUpdateMode; + InstallMode mode; + DPL::String callerPkgId; + + std::string requestedPath; ///input path of widget + bool needEncryption; ///for configuring right task if encryption needed + int certLevel; +}; + +#endif // INSTALLER_CONTEXT_H diff --git a/src_wearable/jobs/widget_install/widget_install_errors.h b/src_wearable/jobs/widget_install/widget_install_errors.h new file mode 100755 index 0000000..59f44d5 --- /dev/null +++ b/src_wearable/jobs/widget_install/widget_install_errors.h @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file installer_errors.h + * @author Pawel Sikorski (p.sikorski@samgsung.com) + * @version + * @brief + */ + +#ifndef INSTALLER_ERRORS_H_ +#define INSTALLER_ERRORS_H_ + +#include +#include +#include + +//TODO SafeException(...) + +using namespace Jobs::Exceptions; + +namespace Jobs { +namespace WidgetInstall { +namespace Exceptions { + +DECLARE_JOB_EXCEPTION_BASE(JobExceptionBase, Base, ErrorUnknown) + +DECLARE_JOB_EXCEPTION(Base, OpenZipFailed, ErrorPackageInvalid) +DECLARE_JOB_EXCEPTION(Base, ZipEmpty, ErrorPackageInvalid) +DECLARE_JOB_EXCEPTION(Base, ExtractFileFailed, ErrorPackageInvalid) +DECLARE_JOB_EXCEPTION(Base, EmptyPluginsDirectory, ErrorPackageInvalid) +DECLARE_JOB_EXCEPTION(Base, PluginsSubdirectory, ErrorPackageInvalid) +DECLARE_JOB_EXCEPTION(Base, RDSDeltaFailure, ErrorPackageInvalid) +DECLARE_JOB_EXCEPTION(Base, MissingConfig, ErrorPackageInvalid) +DECLARE_JOB_EXCEPTION(Base, InvalidStartFile, ErrorPackageInvalid) + +DECLARE_JOB_EXCEPTION(Base, PackageLowerVersion, ErrorPackageLowerVersion) + +DECLARE_JOB_EXCEPTION(Base, ManifestInvalid, ErrorManifestInvalid) + +DECLARE_JOB_EXCEPTION(Base, WidgetConfigFileNotFound, ErrorConfigNotFound) +DECLARE_JOB_EXCEPTION(Base, WidgetConfigFileInvalid, ErrorConfigInvalid) + +DECLARE_JOB_EXCEPTION(Base, SignatureNotFound, ErrorSignatureNotFound) + +DECLARE_JOB_EXCEPTION(Base, SignatureInvalid, ErrorSignatureInvalid) + +DECLARE_JOB_EXCEPTION(Base, SignatureVerificationFailed, ErrorSignatureVerificationFailed) + +DECLARE_JOB_EXCEPTION(Base, RootCertificateNotFound, ErrorRootCertificateNotFound) + +DECLARE_JOB_EXCEPTION(Base, CertificationInvaid, ErrorCertificationInvaid) +DECLARE_JOB_EXCEPTION(Base, NotMatchedCertification, ErrorCertificationInvaid) + +DECLARE_JOB_EXCEPTION(Base, CertificateChainVerificationFailed, ErrorCertificateChainVerificationFailed) + +DECLARE_JOB_EXCEPTION(Base, CertificateExpired, ErrorCertificateExpired) + +DECLARE_JOB_EXCEPTION(Base, NotAllowed, ErrorFatalError) +DECLARE_JOB_EXCEPTION(Base, WidgetRunningError, ErrorFatalError) +DECLARE_JOB_EXCEPTION(Base, DrmDecryptFailed, ErrorFatalError) +DECLARE_JOB_EXCEPTION(Base, DatabaseFailure, ErrorFatalError) +DECLARE_JOB_EXCEPTION(Base, RemovingFolderFailure, ErrorFatalError) +DECLARE_JOB_EXCEPTION(Base, RemovingFileFailure, ErrorFatalError) +DECLARE_JOB_EXCEPTION(Base, CreateVconfFailure, ErrorFatalError) +DECLARE_JOB_EXCEPTION(Base, CopyIconFailed, ErrorFatalError) +DECLARE_JOB_EXCEPTION(Base, FileOperationFailed, ErrorFatalError) +DECLARE_JOB_EXCEPTION(Base, InstallToExternalFailed, ErrorFatalError) +DECLARE_JOB_EXCEPTION(Base, BackupFailed, ErrorFatalError) +DECLARE_JOB_EXCEPTION(Base, InsertNewWidgetFailed, ErrorFatalError) +DECLARE_JOB_EXCEPTION(Base, RemoveBackupFailed, ErrorFatalError) +DECLARE_JOB_EXCEPTION(Base, UpdateFailed, ErrorFatalError) +DECLARE_JOB_EXCEPTION(Base, SetCertificateInfoFailed, ErrorFatalError) +DECLARE_JOB_EXCEPTION(Base, ErrorExternalInstallingFailure, ErrorFatalError) +DECLARE_JOB_EXCEPTION(Base, GetInfoPkgMgrFailed, ErrorFatalError) + +DECLARE_JOB_EXCEPTION(Base, PackageAlreadyInstalled, ErrorPackageAlreadyInstalled) +DECLARE_JOB_EXCEPTION(Base, AceCheckFailed, ErrorAceCheckFailed) +DECLARE_JOB_EXCEPTION(Base, EncryptionFailed, ErrorEncryptionFailed) +DECLARE_JOB_EXCEPTION(Base, InstallOspsvcFailed, ErrorInstallOspServcie) +DECLARE_JOB_EXCEPTION(Base, PrivilegeLevelViolation, ErrorPrivilegeLevelViolation) +DECLARE_JOB_EXCEPTION(Base, NotSupportRDSUpdate, ErrorNotSupportRDSUpdate) +DECLARE_JOB_EXCEPTION(Base, SmackTransactionFailed, ErrorFatalError) +DECLARE_JOB_EXCEPTION(Base, OutOfStorageFailed, ErrorOutOfStorage) +DECLARE_JOB_EXCEPTION(Base, RecoveryFailed, ErrorFatalError) +} //namespace +} //namespace +} //namespace + +#endif /* INSTALLER_ERRORS_H_ */ diff --git a/src_wearable/jobs/widget_install/widget_installer_struct.h b/src_wearable/jobs/widget_install/widget_installer_struct.h new file mode 100644 index 0000000..1fd865e --- /dev/null +++ b/src_wearable/jobs/widget_install/widget_installer_struct.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file widget_installer_struct.h + * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com) + * @author Grzegorz Krawczyk (g.krawczyk@samsung.com) + * @version 1.0 + * @brief Implementation file for widget installer struct + */ +#ifndef WRT_SRC_INSTALLER_CORE_INSTALLER_TASKS_WIDGET_INSTALLER_STRUCT_H_ +#define WRT_SRC_INSTALLER_CORE_INSTALLER_TASKS_WIDGET_INSTALLER_STRUCT_H_ + +//SYSTEM INCLUDES +#include + +//WRT INCLUDES +#include +#include +#include +#include +#include +#include +#include +#include + +//Widget Installer typedefs +typedef void (*InstallerFinishedCallback)( + void *userParam, + std::string tizenId, + Jobs::Exceptions::Type); + +typedef void (*InstallerProgressCallback)(void *userParam, + ProgressPercent percent, + const ProgressDescription &); + +namespace Jobs { +namespace WidgetInstall { +//InstallationStruct +typedef Jobs::JobCallbacksBase +WidgetInstallCallbackBase; + +//Widget Installation Struct +struct WidgetInstallationStruct : public WidgetInstallCallbackBase +{ + InstallMode m_installMode; + std::shared_ptr pkgmgrInterface; + + // It must be empty-constructible as a parameter of generic event + WidgetInstallationStruct() {}; + WidgetInstallationStruct( + InstallerFinishedCallback finished, + InstallerProgressCallback progress, + void *param, + InstallMode mode, + std::shared_ptr + _pkgmgrInterface + ) : + WidgetInstallCallbackBase(finished, progress, param), + m_installMode(mode), + pkgmgrInterface(_pkgmgrInterface) + {} +}; +} // namespace WidgetInstall +} // namespace Jobs + +#endif // WRT_SRC_INSTALLER_CORE_INSTALLER_TASKS_WIDGET_INSTALLER_STRUCT_H_ diff --git a/src_wearable/jobs/widget_install/widget_security.cpp b/src_wearable/jobs/widget_install/widget_security.cpp new file mode 100644 index 0000000..6a6a10f --- /dev/null +++ b/src_wearable/jobs/widget_install/widget_security.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file widget_security.cpp + * @author Krzysztof Jackiewicz(k.jackiewicz@samsung.com) + * @version 1.0 + * @brief + */ + +#include "widget_security.h" +#include +#include + +namespace Jobs { +namespace WidgetInstall { +void WidgetSecurity::getCertificateChainList( + WrtDB::CertificateChainList& list, + WrtDB::CertificateSource source) const +{ + if (source == WrtDB::CertificateSource::SIGNATURE_AUTHOR) { + FOREACH(certIter, mAuthorsCertificateChainList) + list.push_back(certIter->toBase64String()); + } else if (source == WrtDB::CertificateSource::SIGNATURE_DISTRIBUTOR) { + FOREACH(certIter, mCertificateChainList) + list.push_back(certIter->toBase64String()); + } else if (source == WrtDB::CertificateSource::SIGNATURE_DISTRIBUTOR2) { + FOREACH(certIter, mCertificateChainList2) + list.push_back(certIter->toBase64String()); + } else { + _E("UNKNOWN certificate"); + } +} +} // namespace WidgetInstall +} // namespace Jobs diff --git a/src_wearable/jobs/widget_install/widget_security.h b/src_wearable/jobs/widget_install/widget_security.h new file mode 100644 index 0000000..43673be --- /dev/null +++ b/src_wearable/jobs/widget_install/widget_security.h @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file widget_security.h + * @author Krzysztof Jackiewicz(k.jackiewicz@samsung.com) + * @version 1.0 + * @brief + */ + +#ifndef WACSECURITY_H_ +#define WACSECURITY_H_ + +#include +#include +#include + +namespace Jobs { +namespace WidgetInstall { +class WidgetSecurity : public WrtDB::IWidgetSecurity +{ + public: + WidgetSecurity() : + mRecognized(false), + mDistributorSigned(false) + {} + + // from IWidgetSecurity + virtual const WrtDB::WidgetCertificateDataList& getCertificateList() const + { + return mCertificateList; + } + + virtual bool isRecognized() const + { + return mRecognized; + } + + virtual bool isDistributorSigned() const + { + return mDistributorSigned; + } + + virtual void getCertificateChainList( + WrtDB::CertificateChainList& list, + WrtDB::CertificateSource source) const; + + void setRecognized(bool recognized) + { + mRecognized = recognized; + } + void setDistributorSigned(bool distributorSigned) + { + mDistributorSigned = distributorSigned; + } + void setAuthorCertificatePtr(ValidationCore::CertificatePtr certPtr) + { + mAuthorCertificate = certPtr; + } + + ValidationCore::CertificatePtr getAuthorCertificatePtr() const + { + return mAuthorCertificate; + } + + ValidationCore::CertificateCollectionList& getCertificateChainListRef() + { + return mCertificateChainList; + } + + ValidationCore::CertificateCollectionList& getCertificateChainList2Ref() + { + return mCertificateChainList2; + } + + ValidationCore::CertificateCollectionList& + getAuthorsCertificateChainListRef() + { + return mAuthorsCertificateChainList; + } + + WrtDB::WidgetCertificateDataList& getCertificateListRef() + { + return mCertificateList; + } + + private: + // This data are used to evaluate policy + WrtDB::WidgetCertificateDataList mCertificateList; + + // author signature verified + bool mRecognized; + // known distribuor + bool mDistributorSigned; + // Author end entity certificate. + // Information from this certificate are shown to user + // during installation process. + ValidationCore::CertificatePtr mAuthorCertificate; + // This certificates are used by OCSP/CRL + ValidationCore::CertificateCollectionList mCertificateChainList; + // This certificates are for distributor2 + ValidationCore::CertificateCollectionList mCertificateChainList2; + // This authors certificates are used by tizen + ValidationCore::CertificateCollectionList mAuthorsCertificateChainList; +}; +} // namespace WidgetInstall +} // namespace Jobs + +#endif /* WACSECURITY_H_ */ diff --git a/src_wearable/jobs/widget_install/widget_unzip.cpp b/src_wearable/jobs/widget_install/widget_unzip.cpp new file mode 100644 index 0000000..70831ae --- /dev/null +++ b/src_wearable/jobs/widget_install/widget_unzip.cpp @@ -0,0 +1,383 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file widget_unzip.cpp + * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com) + * @version 1.0 + * @brief Implementation file for installer widget unzip + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace WrtDB; + +namespace { +const char *const DRM_LIB_PATH = "/usr/lib/libdrm-service-core-tizen.so"; +const size_t SPACE_SIZE = 1024 * 1024; +const char *const WEB_APP_CONFIG_XML= "config.xml"; +const char *const HYBRID_CONFIG_XML = "res/wgt/config.xml"; + +struct PathAndFilePair +{ + std::string path; + std::string file; + + PathAndFilePair(const std::string &p, + const std::string &f) : + path(p), + file(f) + {} +}; + +PathAndFilePair SplitFileAndPath(const std::string &filePath) +{ + std::string::size_type position = filePath.rfind('/'); + + // Is this only a file without a path ? + if (position == std::string::npos) { + return PathAndFilePair(std::string(), filePath); + } + + // This is full file-path pair + return PathAndFilePair(filePath.substr(0, + position), + filePath.substr(position + 1)); +} +} + +namespace Jobs { +namespace WidgetInstall { + +WidgetUnzip::WidgetUnzip(const std::string &source) +{ + Try { + m_requestFile = getDecryptedPackage(source); + m_zip.reset(new DPL::ZipInput(m_requestFile)); + } + Catch(DPL::ZipInput::Exception::OpenFailed) + { + ReThrowMsg(Exceptions::OpenZipFailed, source); + } + Catch(Exceptions::DrmDecryptFailed) + { + ReThrowMsg(Exceptions::ExtractFileFailed, source); + } +} + +void WidgetUnzip::ExtractFile(DPL::ZipInput::File *input, + const std::string &destFileName) +{ + Try + { + DPL::AbstractWaitableInputAdapter inputAdapter(input); + DPL::FileOutput output(destFileName); + + DPL::Copy(&inputAdapter, &output); + } + Catch(DPL::FileOutput::Exception::OpenFailed) + { + ReThrowMsg(Exceptions::ExtractFileFailed, destFileName); + } + Catch(DPL::CopyFailed) + { + ReThrowMsg(Exceptions::ExtractFileFailed, destFileName); + } +} + +void WidgetUnzip::unzipProgress(const std::string &destination) +{ + // Show file info + _D("Unzipping: '%s', Comment: '%s', Compressed size: %lld, Uncompressed size: %lld", + m_zipIterator->name.c_str(), m_zipIterator->comment.c_str(), m_zipIterator->compressedSize, m_zipIterator->uncompressedSize); + + // Normalize file paths + // FIXME: Implement checking for invalid characters + + // Extract file or path + std::string fileName = m_zipIterator->name; + + if (fileName[fileName.size() - 1] == '/') { + // This is path + std::string newPath = destination + "/" + + fileName.substr(0, fileName.size() - 1); + _D("Path to extract: %s", newPath.c_str()); + + // Create path in case of it is empty + createTempPath(newPath); + } else { + // This is regular file + std::string fileExtractPath = destination + "/" + fileName; + + _D("File to extract: %s", fileExtractPath.c_str()); + + // Split into pat & file pair + PathAndFilePair pathAndFile = SplitFileAndPath(fileExtractPath); + + _D("Path and file: %s : %s", pathAndFile.path.c_str(), pathAndFile.file.c_str()); + + // First, ensure that path exists + createTempPath(pathAndFile.path); + + Try + { + // Open file + std::unique_ptr file( + m_zip->OpenFile(fileName)); + + // Extract single file + ExtractFile(file.get(), fileExtractPath); + } + Catch(DPL::ZipInput::Exception::OpenFileFailed) + { + ThrowMsg(Exceptions::ExtractFileFailed, fileName); + } + } + + // Check whether there are more files to extract + if (++m_zipIterator == m_zip->end()) { + _D("Unzip progress finished successfuly"); + } else { + unzipProgress(destination); + } +} + +bool WidgetUnzip::isDRMPackage(const std::string &source) +{ + _D("Enter : isDRMPackage()"); + int ret = 0; + void* pHandle = NULL; + char* pErrorMsg = NULL; + int (*drm_oem_sapps_is_drm_file)(const char* pDcfPath, int dcfPathLen); + + //TODO: quickfix for platform issues... + if(!DPL::Utils::Path(DRM_LIB_PATH).Exists()) + { + _E("Cannot open %s!", DRM_LIB_PATH); + return false; + } + + pHandle = dlopen(DRM_LIB_PATH, RTLD_LAZY | RTLD_GLOBAL); + if (!pHandle) { + _E("dlopen failed : %s [%s]", source.c_str(), dlerror()); + return false; + } + + // clear existing error + dlerror(); + + drm_oem_sapps_is_drm_file = reinterpret_cast + (dlsym(pHandle, "drm_oem_sapps_is_drm_file")); + + if ((pErrorMsg = dlerror()) != NULL) { + _E("dlsym failed : %s [%s]", source.c_str(), pErrorMsg); + dlclose(pHandle); + return false; + } + + if (drm_oem_sapps_is_drm_file == NULL) { + _E("drm_oem_sapps_is_drm_file is NULL : %s", source.c_str()); + dlclose(pHandle); + return false; + } + + ret = drm_oem_sapps_is_drm_file(source.c_str(), source.length()); + dlclose(pHandle); + if (1 == ret) { + _D("%s is DRM file", source.c_str()); + return true; + } + _D("%s isn't DRM file", source.c_str()); + return false; +} + +bool WidgetUnzip::decryptDRMPackage(const std::string &source, const std::string + &decryptedSource) +{ + _D("Enter : decryptDRMPackage()"); + int ret = 0; + void* pHandle = NULL; + char* pErrorMsg = NULL; + int (*drm_oem_sapps_decrypt_package)(const char* pDcfPath, int dcfPathLen, + const char* pDecryptedFile, int decryptedFileLen); + + pHandle = dlopen(DRM_LIB_PATH, RTLD_LAZY | RTLD_GLOBAL); + if (!pHandle) { + _E("dlopen failed : %s [%s]", source.c_str(), dlerror()); + return false; + } + + // clear existing error + dlerror(); + + drm_oem_sapps_decrypt_package = reinterpret_cast + (dlsym(pHandle, "drm_oem_sapps_decrypt_package")); + + if ((pErrorMsg = dlerror()) != NULL) { + _E("dlsym failed : %s [%s]", source.c_str(), pErrorMsg); + dlclose(pHandle); + return false; + } + + if (drm_oem_sapps_decrypt_package == NULL) { + _E("drm_oem_sapps_decrypt_package is NULL : %s", source.c_str()); + dlclose(pHandle); + return false; + } + + ret = drm_oem_sapps_decrypt_package(source.c_str(), source.length(), + decryptedSource.c_str(), decryptedSource.length()); + dlclose(pHandle); + if (1 == ret) { + _D("%s is decrypted : %s", source.c_str(), decryptedSource.c_str()); + return true; + } + return false; +} + +std::string WidgetUnzip::getDecryptedPackage(const std::string &source) +{ + _D("Check DRM..."); + if (isDRMPackage(source)) { + std::string decryptedFile; + size_t found = source.find_last_of(".wgt"); + if (found == std::string::npos) { + decryptedFile += source + "_tmp.wgt"; + } else { + decryptedFile += source.substr(0, source.find_last_not_of(".wgt") + + 1) + "_tmp.wgt"; + } + + _D("decrypted file name : %s", decryptedFile.c_str()); + if (!decryptDRMPackage(source, decryptedFile)) { + _E("Failed decrypt drm file"); + ThrowMsg(Exceptions::DrmDecryptFailed, source); + } + return decryptedFile; + } + return source; +} + +void WidgetUnzip::unzipWgtFile(const std::string &destination) +{ + _D("Prepare to unzip..."); + Try + { + _D("wgtFile : %s", m_requestFile.c_str()); + _D("Widget package comment: %s", m_zip->GetGlobalComment().c_str()); + + // Widget package must not be empty + if (m_zip->empty()) { + ThrowMsg(Exceptions::ZipEmpty, m_requestFile); + } + + // Set iterator to first file + m_zipIterator = m_zip->begin(); + + unzipProgress(destination); + + // Unzip finished, close internal structures + m_zip.reset(); + + // Done + _D("Unzip finished"); + } + Catch(DPL::ZipInput::Exception::OpenFailed) + { + ReThrowMsg(Exceptions::OpenZipFailed, m_requestFile); + } + Catch(DPL::ZipInput::Exception::SeekFileFailed) + { + ThrowMsg(Exceptions::ExtractFileFailed, m_requestFile); + } + Catch(Exceptions::DrmDecryptFailed) + { + ReThrowMsg(Exceptions::ExtractFileFailed, m_requestFile); + } +} + +bool WidgetUnzip::checkAvailableSpace(const std::string &destination) +{ + _D("checkAvailableSpace ... "); + + double unCompressedSize = m_zip->GetTotalUncompressedSize(); + _D("unCompressedSize : %ld", unCompressedSize); + + struct statvfs vfs; + if (-1 == statvfs(destination.c_str(), &vfs)) { + _E("There is no space for installation"); + return false; + } + + double freeSize = (double)vfs.f_bsize * vfs.f_bavail; + _D("Space Size : %ld", freeSize); + + if (unCompressedSize + SPACE_SIZE >= freeSize) { + _E("There is no space for installation"); + return false; + } + return true; +} + +void WidgetUnzip::unzipConfiguration(const std::string &destination, + WrtDB::PackagingType* type) +{ + _D("unzipConfiguration"); + + Try { + _D("wgtFile : %s", m_requestFile.c_str()); + + std::unique_ptr configFile; + + Try { + configFile.reset(m_zip->OpenFile(HYBRID_CONFIG_XML)); + *type = PKG_TYPE_HYBRID_WEB_APP; + } Catch(DPL::ZipInput::Exception::OpenFileFailed) { + configFile.reset(m_zip->OpenFile(WEB_APP_CONFIG_XML)); + *type = PKG_TYPE_NOMAL_WEB_APP; + } + + std::string extractPath = destination + "/" + WEB_APP_CONFIG_XML; + ExtractFile(configFile.get(), extractPath); + } + Catch(DPL::ZipInput::Exception::OpenFailed) + { + ReThrowMsg(Exceptions::OpenZipFailed, m_requestFile); + } + Catch(DPL::ZipInput::Exception::OpenFileFailed) + { + ThrowMsg(Exceptions::ExtractFileFailed, "config.xml"); + } + Catch(Exceptions::DrmDecryptFailed) + { + ReThrowMsg(Exceptions::ExtractFileFailed, m_requestFile); + } +} + +} //namespace WidgetInstall +} //namespace Jobs diff --git a/src_wearable/jobs/widget_install/widget_unzip.h b/src_wearable/jobs/widget_install/widget_unzip.h new file mode 100644 index 0000000..204cde7 --- /dev/null +++ b/src_wearable/jobs/widget_install/widget_unzip.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file widget_unzip.cpp + * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com) + * @version 1.0 + * @brief Implementation file for installer task unzip + */ +#ifndef WIDGET_UNZIP_H +#define WIDGET_UNZIP_H + +#include + +#include +#include + +namespace Jobs { +namespace WidgetInstall { +class WidgetUnzip +{ + public: + WidgetUnzip(const std::string &source); + void unzipWgtFile(const std::string &destination); + void unzipConfiguration(const std::string &destination, WrtDB::PackagingType *type); + bool checkAvailableSpace(const std::string &destination); + + private: + // Unzip state + std::unique_ptr m_zip; + DPL::ZipInput::const_iterator m_zipIterator; + std::string m_requestFile; + + void unzipProgress(const std::string &destination); + void ExtractFile(DPL::ZipInput::File *input, const std::string + &destFileName); + bool isDRMPackage(const std::string &source); + bool decryptDRMPackage(const std::string &source, const std::string + &decryptedSource); + std::string getDecryptedPackage(const std::string &source); +}; + +} //namespace WidgetInstall +} //namespace Jobs + +#endif // WIDGET_UNZIP_H diff --git a/src_wearable/jobs/widget_install/widget_update_info.cpp b/src_wearable/jobs/widget_install/widget_update_info.cpp new file mode 100644 index 0000000..7c292c7 --- /dev/null +++ b/src_wearable/jobs/widget_install/widget_update_info.cpp @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file widget_update_info.cpp + * @author Chung Jihoon (jihoon.chung@samsung.com) + * @version 1.0 + * @brief Implementation file for WidgetUpdateInfo + */ + +#include "widget_update_info.h" + +WidgetUpdateInfo::WidgetUpdateInfo( + const WrtDB::TizenAppId & appId, + const OptionalWidgetVersion &existingversion, + const OptionalWidgetVersion &incomingversion, + WrtDB::AppType type) : + tzAppId(appId), + existingVersion(existingversion), + incomingVersion(incomingversion), + appType(type) +{ +} + diff --git a/src_wearable/jobs/widget_install/widget_update_info.h b/src_wearable/jobs/widget_install/widget_update_info.h new file mode 100644 index 0000000..2021b42 --- /dev/null +++ b/src_wearable/jobs/widget_install/widget_update_info.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file widget_update_info.h + * @author Chung Jihoon (jihoon.chung@samsung.com) + * @version 1.0 + * @brief Header file for WidgetUpdateInfo + */ +#ifndef SRC_DOMAIN_WIDGET_UPDATE_INFO_H +#define SRC_DOMAIN_WIDGET_UPDATE_INFO_H + +#include +#include + +/** + * WidgetUpdateInfo + * A structure to hold widget's information needed to be registered. + * @see WidgetConfigurationInfo + */ +struct WidgetUpdateInfo +{ + WrtDB::TizenAppId tzAppId; + // Existing widget + OptionalWidgetVersion existingVersion; + // Incoming widget + OptionalWidgetVersion incomingVersion; + // widget type + WrtDB::AppType appType; + + WidgetUpdateInfo() {}; + WidgetUpdateInfo(const WrtDB::TizenAppId & tzAppid, + const OptionalWidgetVersion &existringversion, + const OptionalWidgetVersion &incomingVersion, + const WrtDB::AppType type); +}; + +#endif // SRC_DOMAIN_WIDGET_UPDATE_INFO_H diff --git a/src_wearable/jobs/widget_uninstall/job_widget_uninstall.cpp b/src_wearable/jobs/widget_uninstall/job_widget_uninstall.cpp new file mode 100755 index 0000000..9bb4897 --- /dev/null +++ b/src_wearable/jobs/widget_uninstall/job_widget_uninstall.cpp @@ -0,0 +1,271 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace WrtDB; + +namespace { //anonymous +const char* REG_TIZEN_PKGID_PATTERN = "^[a-zA-Z0-9]{10}$"; +const int PKGID_LENTH = 10; +const DPL::Utils::Path PRELOAD_INSTALLED_PATH("/usr/apps"); + +bool checkDirectoryExist(const std::string& pkgId) +{ + DPL::Utils::Path installPath(GlobalConfig::GetUserInstalledWidgetPath()); + installPath /= pkgId; + return installPath.Exists(); +} +} + +namespace Jobs { +namespace WidgetUninstall { + +class UninstallerTaskFail : + public DPL::TaskDecl +{ + private: + WidgetStatus m_status; + + void StepFail() + { + if (WidgetStatus::NOT_INSTALLED == m_status) { + ThrowMsg(Jobs::WidgetUninstall::Exceptions::WidgetNotExist, + "Widget does not exist"); + } else if (WidgetStatus::PREALOAD == m_status) { + ThrowMsg(Jobs::WidgetUninstall::Exceptions::Unremovable, + "Widget cann't uninstall"); + } else { + Throw(Jobs::WidgetUninstall::Exceptions::Base); + } + } + + public: + UninstallerTaskFail(WidgetStatus status) : + DPL::TaskDecl(this), + m_status(status) + + { + AddStep(&UninstallerTaskFail::StepFail); + } +}; + +JobWidgetUninstall::JobWidgetUninstall( + const std::string & tizenPkgId, + const WidgetUninstallationStruct & + uninstallerStruct) : + Job(Uninstallation), + JobContextBase(uninstallerStruct), + m_id(tizenPkgId), + m_exceptionCaught(Jobs::Exceptions::Success) +{ + using namespace PackageManager; + m_context.removeStarted = false; + m_context.removeFinished = false; + m_context.removeAbnormal = false; + m_context.uninstallStep = UninstallerContext::UNINSTALL_START; + m_context.job = this; + + Try + { + WidgetStatus status = getWidgetStatus(tizenPkgId); + + if (WidgetStatus::Ok == status) { + //TODO: check and save type + + WrtDB::WidgetDAOReadOnly dao(*m_context.tzAppIdList.begin()); + m_context.tzPkgid = DPL::ToUTF8String(dao.getTizenPkgId()); + m_context.locations = WidgetLocation(m_context.tzPkgid); + m_context.locations->registerAppid(DPL::ToUTF8String(*m_context.tzAppIdList.begin())); + m_context.installedPath = + DPL::Utils::Path(*dao.getWidgetInstalledPath()); + m_context.manifestFile = getManifestFile(); + PackagingType packagingType = dao.getPackagingType(); + + _D("Widget model exists. Pkg id : %s", m_context.tzPkgid.c_str()); + + // send start signal of pkgmgr + if (GetInstallerStruct().pkgmgrInterface->setPkgname(m_context.tzPkgid)) + { + GetInstallerStruct().pkgmgrInterface->startJob(InstallationType::Uninstallation); + } + + AddTask(new TaskCheck(m_context)); + if (packagingType == PKG_TYPE_HYBRID_WEB_APP) { + AddTask(new TaskUninstallOspsvc(m_context)); + } + AddTask(new TaskDeletePkgInfo(m_context)); + AddTask(new TaskDbUpdate(m_context)); + AddTask(new TaskSmack(m_context)); + + AddTask(new TaskRemoveCustomHandlers(m_context)); + AddTask(new TaskRemoveFiles(m_context)); + } else if (WidgetStatus::NOT_INSTALLED == status || + WidgetStatus::PREALOAD == status) { + AddTask(new UninstallerTaskFail(status)); + } else if (WidgetStatus::ABNORMAL == status) { + m_context.locations = WidgetLocation(m_context.tzPkgid); + m_context.removeAbnormal = true; + AddTask(new TaskRemoveFiles(m_context)); + } else { + AddTask(new UninstallerTaskFail(WidgetStatus::UNRECOGNIZED)); + } + } Catch(WidgetDAOReadOnly::Exception::Base) { + AddTask(new UninstallerTaskFail(WidgetStatus::UNRECOGNIZED)); + } +} + +WidgetStatus JobWidgetUninstall::getWidgetStatus(const std::string &id) +{ + regex_t regx; + if(regcomp(®x, REG_TIZEN_PKGID_PATTERN, REG_NOSUB | REG_EXTENDED)!=0){ + _D("Regcomp failed"); + } + std::string pkgId = id; + DPL::Utils::Path installPath; + if ((regexec(®x, id.c_str(), + static_cast(0), NULL, 0) != REG_NOERROR)) { + //appid was passed + pkgId = id.substr(0, PKGID_LENTH); + + //Service app cannot uninstall by appid + WrtDB::WidgetDAOReadOnly dao(DPL::FromUTF8String(id)); + if( dao.getWidgetType().appType == APP_TYPE_TIZENWEBSERVICE ){ + _E("Service app cannot uninstall by appid"); + return WidgetStatus::NOT_INSTALLED; + } + } + + m_context.tzAppIdList = WrtDB::WidgetDAOReadOnly::getTzAppIdList(DPL::FromUTF8String(pkgId)); + if( m_context.tzAppIdList.empty() ){ + if(checkDirectoryExist(pkgId)) { + _E("installed widget status is abnormal"); + return WidgetStatus::ABNORMAL; + } + return WidgetStatus::NOT_INSTALLED; + } + return WidgetStatus::Ok; +} + +std::string JobWidgetUninstall::getRemovedTizenId() const +{ + return m_id; +} + +bool JobWidgetUninstall::getRemoveStartedFlag() const +{ + return m_context.removeStarted; +} + +bool JobWidgetUninstall::getRemoveFinishedFlag() const +{ + return m_context.removeFinished; +} + +DPL::Utils::Path JobWidgetUninstall::getManifestFile() const +{ + std::ostringstream manifest_name; + manifest_name << m_context.tzPkgid << ".xml"; + DPL::Utils::Path manifestFile; + + const DPL::Utils::Path PRELOAD_INSTALLED_PATH("/usr/apps/" + m_context.tzPkgid); + const DPL::Utils::Path USR_PACKAGES_PATH("/usr/share/packages"); + const DPL::Utils::Path OPT_PACKAGES_PATH("/opt/share/packages"); + + if (PRELOAD_INSTALLED_PATH == m_context.installedPath) { + _D("This widget is preloaded."); + manifestFile = USR_PACKAGES_PATH; + } else { + manifestFile = OPT_PACKAGES_PATH; + } + + manifestFile /= manifest_name.str(); + _D("Manifest file : %s", manifestFile.Fullpath().c_str()); + + return manifestFile; +} + +void JobWidgetUninstall::SendProgress() +{ + using namespace PackageManager; + if (!getRemoveStartedFlag() || + (getRemoveStartedFlag() && getRemoveFinishedFlag())) + { + if (NULL != GetInstallerStruct().progressCallback) { + // send progress signal of pkgmgr + std::ostringstream percent; + percent << static_cast(GetProgressPercent()); + + _D("Call widget uninstall progressCallback"); + GetInstallerStruct().progressCallback( + GetInstallerStruct().userParam, + GetProgressPercent(), GetProgressDescription()); + } + } +} + +void JobWidgetUninstall::SendFinishedSuccess() +{ + using namespace PackageManager; + // send signal of pkgmgr + GetInstallerStruct().pkgmgrInterface->endJob(m_exceptionCaught); + + _D("Call widget uninstall success finishedCallback"); + GetInstallerStruct().finishedCallback(GetInstallerStruct().userParam, + getRemovedTizenId(), + Jobs::Exceptions::Success); +} + +void JobWidgetUninstall::SendFinishedFailure() +{ + using namespace PackageManager; + + LOGE(COLOR_ERROR "Error in uninstallation step: %d" COLOR_END, m_exceptionCaught); + LOGE(COLOR_ERROR "Message: %s" COLOR_END, m_exceptionMessage.c_str()); + fprintf(stderr, "[Err:%d] %s", m_exceptionCaught, m_exceptionMessage.c_str()); + + // send signal of pkgmgr + GetInstallerStruct().pkgmgrInterface->endJob(m_exceptionCaught); + + _D("Call widget uninstall failure finishedCallback"); + GetInstallerStruct().finishedCallback(GetInstallerStruct().userParam, + getRemovedTizenId(), + m_exceptionCaught); + _D("[JobWidgetUninstall] Asynchronous failure callback status sent"); +} + +void JobWidgetUninstall::SaveExceptionData(const Jobs::JobExceptionBase &e) +{ + m_exceptionCaught = static_cast(e.getParam()); + m_exceptionMessage = e.GetMessage(); +} +} //namespace WidgetUninstall +} //namespace Jobs diff --git a/src_wearable/jobs/widget_uninstall/job_widget_uninstall.h b/src_wearable/jobs/widget_uninstall/job_widget_uninstall.h new file mode 100755 index 0000000..d7406ed --- /dev/null +++ b/src_wearable/jobs/widget_uninstall/job_widget_uninstall.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file job_widet_uninstall.h + * @brief Uninstaller header file. + * @author Radoslaw Wicik r.wicik@samsung.com + */ + +#ifndef WRT_SRC_INSTALLER_CORE_JOB_WIDGET_UNINSTALL_JOB_WIDGET_UNINSTALL_H_ +#define WRT_SRC_INSTALLER_CORE_JOB_WIDGET_UNINSTALL_JOB_WIDGET_UNINSTALL_H_ + +#include +#include +#include +#include +#include + +namespace Jobs { +namespace WidgetUninstall { + +enum class WidgetStatus +{ + Ok, NOT_INSTALLED, PREALOAD, ABNORMAL, UNRECOGNIZED +}; + +typedef JobContextBase WidgetUnistallStructBase; +typedef JobProgressBase UninstallContextBase; + +class JobWidgetUninstall : + public Job, + public UninstallContextBase, + public WidgetUnistallStructBase +{ + private: + UninstallerContext m_context; + + //TODO move it to base class of all jobs + Jobs::Exceptions::Type m_exceptionCaught; + std::string m_exceptionMessage; + // It canbe pkgid or tzAppid + std::string m_id; + + public: + /** + * @brief Uninstaller must to know which widget to uninstall. + * + * @param[in] WrtDB::TizenAppId tzAppId - widget to uninstall + */ + JobWidgetUninstall(const std::string &tizenPkgIdorTizenAppId, + const WidgetUninstallationStruct& uninstallerStruct); + + std::string getRemovedTizenId() const; + bool getRemoveStartedFlag() const; + bool getRemoveFinishedFlag() const; + DPL::Utils::Path getManifestFile() const; + + WidgetStatus getWidgetStatus(const std::string &tizenPkgIdorTizenAppId); + + void SendProgress(); + void SendFinishedSuccess(); + void SendFinishedFailure(); + void SaveExceptionData(const Jobs::JobExceptionBase &e); +}; +} //namespace WidgetUninstall +} //namespace Jobs + +#endif // WRT_SRC_INSTALLER_CORE_JOB_WIDGET_UNINSTALL_JOB_WIDGET_UNINSTALL_H_ diff --git a/src_wearable/jobs/widget_uninstall/task_check.cpp b/src_wearable/jobs/widget_uninstall/task_check.cpp new file mode 100755 index 0000000..648cdf1 --- /dev/null +++ b/src_wearable/jobs/widget_uninstall/task_check.cpp @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file task_check.cpp + * @author Pawel Sikorski(p.sikorski@samsung.com) + * @version 1.0 + * @brief Header file for widget uninstall task check + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Jobs { +namespace WidgetUninstall { +TaskCheck::TaskCheck(UninstallerContext& context) : + DPL::TaskDecl(this), + m_context(context) +{ + AddStep(&TaskCheck::StartStep); + AddStep(&TaskCheck::StepUninstallPreCheck); + AddStep(&TaskCheck::StepCheckMDM); + AddStep(&TaskCheck::EndStep); +} + +TaskCheck::~TaskCheck() +{} + +void TaskCheck::StartStep() +{ + LOGD("--------- : START ----------"); +} + +void TaskCheck::EndStep() +{ + m_context.job->UpdateProgress(UninstallerContext::UNINSTALL_PRECHECK, + "Uninstall pre-checking Finished"); + LOGD("--------- : END ----------"); +} + +void TaskCheck::StepUninstallPreCheck() +{ + FOREACH(it , m_context.tzAppIdList){ + bool isRunning = false; + std::string tzAppId = DPL::ToUTF8String(*it); + int ret = app_manager_is_running(tzAppId.c_str(), &isRunning); + if (APP_MANAGER_ERROR_NONE != ret) { + _E("Fail to get running state"); + ThrowMsg(Exceptions::PlatformAPIFailure, + "Fail to get widget state"); + } + + if (true == isRunning) { + // get app_context for running application + // app_context must be released with app_context_destroy + app_context_h appCtx = NULL; + ret = app_manager_get_app_context(tzAppId.c_str(), &appCtx); + if (APP_MANAGER_ERROR_NONE != ret) { + _E("Fail to get app_context"); + ThrowMsg(Exceptions::AppIsRunning, + "Widget is not stopped. Cannot uninstall!"); + } + + // terminate app_context_h + ret = app_manager_terminate_app(appCtx); + if (APP_MANAGER_ERROR_NONE != ret) { + _E("Fail to terminate running application"); + app_context_destroy(appCtx); + ThrowMsg(Exceptions::AppIsRunning, + "Widget is not stopped. Cannot uninstall!"); + } else { + app_context_destroy(appCtx); + // app_manager_terminate_app isn't sync API + // wait until application isn't running (50ms * 100) + bool isStillRunning = true; + int checkingloop = 100; + struct timespec duration = { 0, 50 * 1000 * 1000 }; + while (--checkingloop >= 0) { + nanosleep(&duration, NULL); + int ret = app_manager_is_running(tzAppId.c_str(), &isStillRunning); + if (APP_MANAGER_ERROR_NONE != ret) { + _E("Fail to get running state"); + ThrowMsg(Exceptions::PlatformAPIFailure, + "Fail to get widget state"); + } + if (!isStillRunning) { + break; + } + } + if (isStillRunning) { + _E("Fail to terminate running application"); + ThrowMsg(Exceptions::AppIsRunning, + "Widget is not stopped. Cannot uninstall!"); + } + _D("terminate application"); + } + } + } + + // check if this webapp has dynamic boxes, and request to remove them + web_provider_service_wait_boxes_removed(m_context.tzAppid.c_str()); + _D("web app(%s) and its dynamic boxes can be terminated.", m_context.tzAppid.c_str()); +} + +void TaskCheck::StepCheckMDM() +{ + _D("StepCheckMDM"); + + if (PMINFO_R_OK != pkgmgr_parser_check_mdm_policy_for_uninstallation( + m_context.manifestFile.Fullpath().c_str())) { + _E("Failed to check mdm policy"); + ThrowMsg(Exceptions::CheckMDMPolicyFailure, "Can't uninstall! Because of MDM policy"); + } +} +} //namespace WidgetUninstall +} //namespace Jobs diff --git a/src_wearable/jobs/widget_uninstall/task_check.h b/src_wearable/jobs/widget_uninstall/task_check.h new file mode 100644 index 0000000..29c00db --- /dev/null +++ b/src_wearable/jobs/widget_uninstall/task_check.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file task_check.h + * @author Pawel Sikorski(p.sikorski@samsung.com) + * @version 1.0 + * @brief Header file for widget uninstall task check + */ + +#ifndef WRT_SRC_INSTALLER_CORE_JOB_WIDGET_UNINSTALL_TASK_CHECK_H_ +#define WRT_SRC_INSTALLER_CORE_JOB_WIDGET_UNINSTALL_TASK_CHECK_H_ + +#include + +struct UninstallerContext; //forward declaration +class WidgetModel; + +namespace Jobs { +namespace WidgetUninstall { +class TaskCheck : + public DPL::TaskDecl +{ + private: + //context + UninstallerContext& m_context; + + //steps + void StepUninstallPreCheck(); + void StepCheckMDM(); + void StartStep(); + void EndStep(); + + public: + TaskCheck(UninstallerContext& context); + virtual ~TaskCheck(); +}; +} //namespace WidgetUninstall +} //namespace Jobs + +#endif /* WRT_SRC_INSTALLER_CORE_JOB_WIDGET_UNINSTALL_TASK_CHECK_H_ */ diff --git a/src_wearable/jobs/widget_uninstall/task_db_update.cpp b/src_wearable/jobs/widget_uninstall/task_db_update.cpp new file mode 100755 index 0000000..0c391fd --- /dev/null +++ b/src_wearable/jobs/widget_uninstall/task_db_update.cpp @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file task_db_update.cpp + * @author Lukasz Wrzosek(l.wrzosek@samsung.com) + * @version 1.0 + * @brief Implementation file for uninstaller task database updating + */ + +#ifdef DBOX_ENABLED +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace WrtDB; + +namespace Jobs { +namespace WidgetUninstall { +TaskDbUpdate::TaskDbUpdate(UninstallerContext& context) : + DPL::TaskDecl(this), + m_context(context) +{ + AddStep(&TaskDbUpdate::StartStep); + AddStep(&TaskDbUpdate::StepRemoveExternalLocations); + AddStep(&TaskDbUpdate::StepDbUpdate); +#ifdef DBOX_ENABLED + AddStep(&TaskDbUpdate::StepLiveboxDBDelete); +#endif + AddStep(&TaskDbUpdate::EndStep); +} + +TaskDbUpdate::~TaskDbUpdate() +{} + +void TaskDbUpdate::StepDbUpdate() +{ + Try + { + //TODO: widget handle should not be used any more + FOREACH(it , m_context.tzAppIdList){ + ace_unregister_widget(static_cast(WidgetDAOReadOnly::getHandle(*it))); + WidgetDAO::unregisterWidget(*it); + } + _D("Unregistered widget successfully!"); + } + Catch(DPL::DB::SqlConnection::Exception::Base) + { + _E("Failed to handle StepDbUpdate!"); + ReThrowMsg(Exceptions::DatabaseFailure, + "Failed to handle StepDbUpdate!"); + } +} + +#ifdef DBOX_ENABLED +void TaskDbUpdate::StepLiveboxDBDelete() +{ + FOREACH(it, m_context.tzAppIdList){ + int ret = + web_provider_livebox_delete_by_app_id(DPL::ToUTF8String(*it).c_str()); + + if (ret < 0) { + _D("failed to delete box info"); + } else { + _D("delete box info: %s", it); + } + } +} +#endif + +void TaskDbUpdate::StepRemoveExternalLocations() +{ + if (!m_context.removeAbnormal) { + FOREACH(it, m_context.tzAppIdList){ + WidgetDAO dao(*it); + _D("Removing external locations:"); + WrtDB::ExternalLocationList externalPaths = dao.getWidgetExternalLocations(); + FOREACH(file, externalPaths) + { + DPL::Utils::Path path(*file); + if(path.Exists()){ + if(path.IsFile()){ + _D(" -> %s", path.Fullpath().c_str()); + Try { + DPL::Utils::Remove(path); + } Catch(DPL::Utils::Path::BaseException){ + _E("Failed to remove the file: %s", path.Fullpath().c_str()); + } + } else if (path.IsDir()){ + _D(" -> %s", path.Fullpath().c_str()); + Try { + DPL::Utils::Remove(path); + } Catch(DPL::Utils::Path::BaseException){ + Throw(Jobs::WidgetUninstall::TaskDbUpdate:: + Exception::RemoveFilesFailed); + } + } + } else { + _W(" -> %s(no such a path)", path.Fullpath().c_str()); + } + } + dao.unregisterAllExternalLocations(); + } + } +} + +void TaskDbUpdate::StartStep() +{ + LOGD("--------- : START ----------"); +} + +void TaskDbUpdate::EndStep() +{ + m_context.job->UpdateProgress( + UninstallerContext::UNINSTALL_DB_UPDATE, + "Widget DB Update Finished"); + + LOGD("--------- : END ----------"); +} +} //namespace WidgetUninstall +} //namespace Jobs diff --git a/src_wearable/jobs/widget_uninstall/task_db_update.h b/src_wearable/jobs/widget_uninstall/task_db_update.h new file mode 100644 index 0000000..3b74ad5 --- /dev/null +++ b/src_wearable/jobs/widget_uninstall/task_db_update.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file task_db_update.h + * @author Lukasz Wrzosek(l.wrzosek@samsung.com) + * @version 1.0 + * @brief Header file for uninstaller task database updating + */ + +#ifndef WRT_SRC_INSTALLER_CORE_JOB_WIDGET_UNINSTALL_TASK_DB_UPDATE_H_ +#define WRT_SRC_INSTALLER_CORE_JOB_WIDGET_UNINSTALL_TASK_DB_UPDATE_H_ + +#include +#include +#include + +class UninstallerContext; + +namespace Jobs { +namespace WidgetUninstall { +class TaskDbUpdate : + public DPL::TaskDecl +{ + class Exception + { + public: + DECLARE_EXCEPTION_TYPE(DPL::Exception, Base) + DECLARE_EXCEPTION_TYPE(Base, DbStepFailed) + DECLARE_EXCEPTION_TYPE(Base, RemoveFilesFailed) + }; + + UninstallerContext& m_context; + + private: + void StepDbUpdate(); + void StepLiveboxDBDelete(); + void StepRemoveExternalLocations(); + + void StartStep(); + void EndStep(); + + public: + TaskDbUpdate(UninstallerContext& context); + virtual ~TaskDbUpdate(); +}; +} //namespace WidgetUninstall +} //namespace Jobs + +#endif // WRT_SRC_INSTALLER_CORE_JOB_WIDGET_UNINSTALL_TASK_DB_UPDATE_H_ diff --git a/src_wearable/jobs/widget_uninstall/task_delete_pkginfo.cpp b/src_wearable/jobs/widget_uninstall/task_delete_pkginfo.cpp new file mode 100644 index 0000000..cf2aa0e --- /dev/null +++ b/src_wearable/jobs/widget_uninstall/task_delete_pkginfo.cpp @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file task_delete_pkginfo.cpp + * @author Leerang Song(leerang.song@samsung.com) + * @version 1.0 + * @brief Implementation file for uninstaller delete package information + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Jobs { +namespace WidgetUninstall { +TaskDeletePkgInfo::TaskDeletePkgInfo( + UninstallerContext& context) : + DPL::TaskDecl(this), + m_context(context) +{ + AddStep(&TaskDeletePkgInfo::StartStep); + AddStep(&TaskDeletePkgInfo::StepDeletePkgInfo); + AddStep(&TaskDeletePkgInfo::EndStep); +} + +void TaskDeletePkgInfo::StartStep() +{ + LOGD("--------- : START ----------"); +} + +void TaskDeletePkgInfo::EndStep() +{ + LOGD("--------- : END ----------"); +} + +void TaskDeletePkgInfo::StepDeletePkgInfo() +{ + std::ostringstream manifest_name; + manifest_name << m_context.tzPkgid << ".xml"; + DPL::Utils::Path pre_manifest("/usr/share/packages"); + pre_manifest /= manifest_name.str(); + + if (!(m_context.manifestFile.Exists() == 0 && pre_manifest.Exists())) { + if (0 != pkgmgr_parser_parse_manifest_for_uninstallation( + m_context.manifestFile.Fullpath().c_str(), NULL)) { + _W("Manifest file failed to parse for uninstallation"); + } + } + if (!DPL::Utils::TryRemove(m_context.manifestFile)) { + _W("No manifest file found: %s", m_context.manifestFile.Fullpath().c_str()); + } else { + _D("Manifest file removed: %s", m_context.manifestFile.Fullpath().c_str()); + } +} +} //namespace WidgetUninstall +} //namespace Jobs diff --git a/src_wearable/jobs/widget_uninstall/task_delete_pkginfo.h b/src_wearable/jobs/widget_uninstall/task_delete_pkginfo.h new file mode 100644 index 0000000..4624c4a --- /dev/null +++ b/src_wearable/jobs/widget_uninstall/task_delete_pkginfo.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file task_delete_pkginfo.h + * @author Leerang Song(leerang.song@samsung.com) + * @version 1.0 + * @brief Header file for uninstaller task delete package infomation + */ + +#ifndef WRT_SRC_INSTALLER_CORE_JOB_WIDGET_UNINSTALL_TASK_DELETE_PKGINFO_H_ +#define WRT_SRC_INSTALLER_CORE_JOB_WIDGET_UNINSTALL_TASK_DELETE_PKGINFO_H_ + +#include +#include + +struct UninstallerContext; + +namespace Jobs { +namespace WidgetUninstall { +class TaskDeletePkgInfo : + public DPL::TaskDecl +{ + UninstallerContext& m_context; + + private: + void StepDeletePkgInfo(); + + void StartStep(); + void EndStep(); + + public: + TaskDeletePkgInfo(UninstallerContext& context); +}; +} //namespace WidgetUninstall +} //namespace Jobs + +#endif +// WRT_SRC_INSTALLER_CORE_JOB_WIDGET_UNINSTALL_TASK_DELETE_PKGINFO_H_ diff --git a/src_wearable/jobs/widget_uninstall/task_remove_custom_handlers.cpp b/src_wearable/jobs/widget_uninstall/task_remove_custom_handlers.cpp new file mode 100755 index 0000000..4a7ad32 --- /dev/null +++ b/src_wearable/jobs/widget_uninstall/task_remove_custom_handlers.cpp @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file task_remove_custom_handlers.cpp + * @author Przemyslaw Ciezkowski (p.ciezkowski@samsung.com) + * @version 1.0 + * @brief File for uninstaller - remove custom handlers + */ + +#include +#include +#include +#include +#include +#include +#include + +namespace Jobs { +namespace WidgetUninstall { +TaskRemoveCustomHandlers::TaskRemoveCustomHandlers(UninstallerContext& context) + : + DPL::TaskDecl(this), + m_context(context) +{ + AddStep(&TaskRemoveCustomHandlers::StartStep); + AddStep(&TaskRemoveCustomHandlers::Step); + AddStep(&TaskRemoveCustomHandlers::EndStep); +} + +void TaskRemoveCustomHandlers::Step() +{ + CustomHandlerDB::Interface::attachDatabaseRW(); + FOREACH(it, m_context.tzAppIdList){ + _D("Removing widget from appsvc"); + int result = appsvc_unset_defapp(DPL::ToUTF8String(*it).c_str()); + _D("Result: %d", result); + + CustomHandlerDB::CustomHandlerDAO handlersDao(*it); + handlersDao.removeWidgetProtocolHandlers(); + handlersDao.removeWidgetContentHandlers(); + } + CustomHandlerDB::Interface::detachDatabase(); +} + +void TaskRemoveCustomHandlers::StartStep() +{ + LOGD("--------- : START ----------"); +} + +void TaskRemoveCustomHandlers::EndStep() +{ + LOGD("--------- : END ----------"); +} +} //namespace WidgetUninstall +} //namespace Jobs diff --git a/src_wearable/jobs/widget_uninstall/task_remove_custom_handlers.h b/src_wearable/jobs/widget_uninstall/task_remove_custom_handlers.h new file mode 100644 index 0000000..e6458b9 --- /dev/null +++ b/src_wearable/jobs/widget_uninstall/task_remove_custom_handlers.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file task_remove_custom_handlers.h + * @author Przemyslaw Ciezkowski (p.ciezkowski@samsung.com) + * @version 1.0 + * @brief Header file for uninstaller - remove custom handlers + */ +#ifndef INSTALLER_CORE_JOBS_WIDGET_UNINSTALL_TASK_REMOVE_CUSTOM_HANDLERS_H +#define INSTALLER_CORE_JOBS_WIDGET_UNINSTALL_TASK_REMOVE_CUSTOM_HANDLERS_H + +#include + +class UninstallerContext; + +namespace Jobs { +namespace WidgetUninstall { +class TaskRemoveCustomHandlers : + public DPL::TaskDecl +{ + private: + UninstallerContext& m_context; + + void Step(); + + void StartStep(); + void EndStep(); + + public: + TaskRemoveCustomHandlers(UninstallerContext& context); +}; +} //namespace WidgetUninstall +} //namespace Jobs + +#endif /* INSTALLER_CORE_JOBS_WIDGET_UNINSTALL_TASK_REMOVE_CUSTOM_HANDLERS_H */ diff --git a/src_wearable/jobs/widget_uninstall/task_remove_files.cpp b/src_wearable/jobs/widget_uninstall/task_remove_files.cpp new file mode 100644 index 0000000..daf4542 --- /dev/null +++ b/src_wearable/jobs/widget_uninstall/task_remove_files.cpp @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file task_remove_files.cpp + * @author Lukasz Wrzosek(l.wrzosek@samsung.com) + * @version 1.0 + * @brief Implementation file for uninstaller task for removing widget files + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Jobs { +namespace WidgetUninstall { +using namespace WrtDB; + +TaskRemoveFiles::TaskRemoveFiles(UninstallerContext& context) : + DPL::TaskDecl(this), + m_context(context) +{ + AddStep(&TaskRemoveFiles::StartStep); + AddStep(&TaskRemoveFiles::StepRemoveInstallationDirectory); + AddStep(&TaskRemoveFiles::StepRemoveFinished); + AddStep(&TaskRemoveFiles::EndStep); +} + +TaskRemoveFiles::~TaskRemoveFiles() +{} + +void TaskRemoveFiles::StepRemoveInstallationDirectory() +{ + _D("StepRemoveInstallationDirectory started"); + Try { + int ret = app2ext_get_app_location(m_context.tzPkgid.c_str()); + + if (APP2EXT_SD_CARD == ret) { + _D("Remove external directory"); + Try { + WidgetInstallToExtSingleton::Instance().initialize(m_context.tzPkgid); + WidgetInstallToExtSingleton::Instance().uninstallation(); + WidgetInstallToExtSingleton::Instance().deinitialize(); + } + Catch(WidgetInstallToExt::Exception::ErrorInstallToExt) + { + // Continue uninstall even fail to remove external directory. + // i.e.) SD card isn't inserted or unmounted. + // This behavior is recommended by platform(app2sd maintainer). + _E("Fail to remove external directory"); + } + } + if (APP2EXT_NOT_INSTALLED != ret) { + _D("Removing directory"); + m_context.removeStarted = true; + DPL::Utils::Path widgetDir= m_context.installedPath; + Try{ + DPL::Utils::Remove(widgetDir); + } Catch(DPL::Utils::Path::BaseException){ + _E("Removing widget installation directory failed : %s", widgetDir.Fullpath().c_str()); + } + DPL::Utils::Path dataDir(m_context.locations->getUserDataRootDir()); + Try{ + DPL::Utils::Remove(dataDir); + } Catch(DPL::Utils::Path::BaseException){ + _W("%s is already removed", dataDir.Fullpath().c_str()); + } + } else { + _E("app is not installed"); + ThrowMsg(Exceptions::WidgetNotExist, "failed to get app location"); + } + } Catch(Exception::RemoveFilesFailed) { + ThrowMsg(Exceptions::RemoveFileFailure, "Cann't remove directory"); + } + m_context.job->UpdateProgress( + UninstallerContext::UNINSTALL_REMOVE_WIDGETDIR, + "Widget INstallation Directory Removal Finished"); +} + +void TaskRemoveFiles::StepRemoveFinished() +{ + _D("StepRemoveFinished finished"); + + m_context.job->UpdateProgress( + UninstallerContext::UNINSTALL_REMOVE_FINISHED, + "Widget remove steps Finished"); +} + +void TaskRemoveFiles::StartStep() +{ + LOGD("--------- : START ----------"); +} + +void TaskRemoveFiles::EndStep() +{ + LOGD("--------- : END ----------"); +} +} //namespace WidgetUninstall +} //namespace Jobs diff --git a/src_wearable/jobs/widget_uninstall/task_remove_files.h b/src_wearable/jobs/widget_uninstall/task_remove_files.h new file mode 100644 index 0000000..276fb24 --- /dev/null +++ b/src_wearable/jobs/widget_uninstall/task_remove_files.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file task_remove_files.h + * @author Lukasz Wrzosek(l.wrzosek@samsung.com) + * @version 1.0 + * @brief Header file for uninstaller task remove files + */ + +#ifndef WRT_SRC_INSTALLER_CORE_JOB_WIDGET_UNINSTALL_TASK_REMOVE_FILES_H_ +#define WRT_SRC_INSTALLER_CORE_JOB_WIDGET_UNINSTALL_TASK_REMOVE_FILES_H_ + +//forward declaration +struct UninstallerContext; + +#include +#include + +#include + +namespace Jobs { +namespace WidgetUninstall { +class TaskRemoveFiles : + public DPL::TaskDecl +{ + class Exception + { + public: + DECLARE_EXCEPTION_TYPE(DPL::Exception, Base) + DECLARE_EXCEPTION_TYPE(Base, RemoveFilesFailed) + }; + + UninstallerContext& m_context; + + private: + void StepRemoveInstallationDirectory(); + void StepRemoveFinished(); + + void StartStep(); + void EndStep(); + + public: + explicit TaskRemoveFiles(UninstallerContext& context); + virtual ~TaskRemoveFiles(); +}; +} //namespace WidgetUninstall +} //namespace Jobs + +#endif // WRT_SRC_INSTALLER_CORE_JOB_WIDGET_UNINSTALL_TASK_REMOVE_FILES_H_ diff --git a/src_wearable/jobs/widget_uninstall/task_smack.cpp b/src_wearable/jobs/widget_uninstall/task_smack.cpp new file mode 100644 index 0000000..9599c92 --- /dev/null +++ b/src_wearable/jobs/widget_uninstall/task_smack.cpp @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file task_smack.cpp + * @author Piotr Kozbial (p.kozbial@samsung.com) + * @version 1.0 + * @brief Implementation file for installer task smack + */ + +#include +#include +#include +#include +#include +#include + +namespace Jobs { +namespace WidgetUninstall { +TaskSmack::TaskSmack(UninstallerContext& context) : + DPL::TaskDecl(this), + m_context(context) +{ + AddStep(&TaskSmack::StartStep); + AddStep(&TaskSmack::Step); + AddStep(&TaskSmack::EndStep); +} + +void TaskSmack::Step() +{ + _D("------------------------> SMACK: Jobs::WidgetUninstall::TaskSmack::Step()"); + + if (PC_OPERATION_SUCCESS != perm_begin()) { + _E("failure in smack transaction begin"); + return; + } + + const char* pkgId = m_context.tzPkgid.c_str(); + if (PC_OPERATION_SUCCESS != perm_app_revoke_permissions(pkgId)) { + _E("failure in revoking smack permissions"); + } + + if (PC_OPERATION_SUCCESS != perm_app_uninstall(pkgId)) { + _E("failure in removing smack rules file"); + } + + if (PC_OPERATION_SUCCESS != perm_end()) { + _E("failure in smack transaction end"); + return; + } +} + +void TaskSmack::StartStep() +{ + LOGD("--------- : START ----------"); +} + +void TaskSmack::EndStep() +{ + m_context.job->UpdateProgress( + UninstallerContext::UNINSTALL_SMACK_DISABLE, + "Widget SMACK Disabled"); + + LOGD("--------- : END ----------"); +} +} //namespace WidgetUninstall +} //namespace Jobs diff --git a/src_wearable/jobs/widget_uninstall/task_smack.h b/src_wearable/jobs/widget_uninstall/task_smack.h new file mode 100644 index 0000000..c7886b9 --- /dev/null +++ b/src_wearable/jobs/widget_uninstall/task_smack.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file task_smack.h + * @author Piotr Kozbial (p.kozbial@samsung.com) + * @version 1.0 + * @brief Header file for uninstaller task smack + */ +#ifndef INSTALLER_CORE_JOS_WIDGET_UNINSTALL_TASK_SMACK_H +#define INSTALLER_CORE_JOS_WIDGET_UNINSTALL_TASK_SMACK_H + +#include + +class UninstallerContext; + +namespace Jobs { +namespace WidgetUninstall { +class TaskSmack : + public DPL::TaskDecl +{ + private: + UninstallerContext& m_context; + + void Step(); + + void StartStep(); + void EndStep(); + + public: + TaskSmack(UninstallerContext& context); +}; +} //namespace WidgetUninstall +} //namespace Jobs + +#endif /* INSTALLER_CORE_JOS_WIDGET_UNINSTALL_TASK_SMACK_H */ diff --git a/src_wearable/jobs/widget_uninstall/task_uninstall_ospsvc.cpp b/src_wearable/jobs/widget_uninstall/task_uninstall_ospsvc.cpp new file mode 100644 index 0000000..9d00ea1 --- /dev/null +++ b/src_wearable/jobs/widget_uninstall/task_uninstall_ospsvc.cpp @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file task_uninstall_ospsvc.cpp + * @author Soyoung Kim(sy037.kim@samsung.com) + * @version 1.0 + * @brief Header file for widget uninstall task to uninstall ospsvc + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace WrtDB; + +namespace { +const int MAX_BUF_SIZE = 128; +const char* OSP_INSTALL_STR = "/usr/etc/package-manager/backend/tpk -uv "; +} + +namespace Jobs { +namespace WidgetUninstall { +TaskUninstallOspsvc::TaskUninstallOspsvc(UninstallerContext& context) : + DPL::TaskDecl(this), + m_context(context) +{ + AddStep(&TaskUninstallOspsvc::StartStep); + AddStep(&TaskUninstallOspsvc::StepUninstallOspsvc); + AddStep(&TaskUninstallOspsvc::EndStep); +} + +TaskUninstallOspsvc::~TaskUninstallOspsvc() +{} + +void TaskUninstallOspsvc::StepUninstallOspsvc() +{ + _D("Step : Uninstall Osp service"); + + std::ostringstream commStr; + commStr << OSP_INSTALL_STR << BashUtils::escape_arg(m_context.tzPkgid); + _D("osp uninstall command : %s", commStr.str().c_str()); + + char readBuf[MAX_BUF_SIZE]; + FILE *fd; + fd = popen(commStr.str().c_str(), "r"); + if (NULL == fd) { + _E("Failed to uninstalltion osp service"); + ThrowMsg(Exceptions::UninstallOspSvcFailed, + "Error occurs during\ + uninstall osp service"); + } + + if(fgets(readBuf, MAX_BUF_SIZE, fd) == NULL) + { + _E("Failed to uninstalltion osp service\ + Inability of reading file."); + ThrowMsg(Exceptions::UninstallOspSvcFailed, + "Error occurs during\ + uninstall osp service"); + } + _D("return value : %s", readBuf); + + int result = atoi(readBuf); + if (0 != result) { + ThrowMsg(Exceptions::UninstallOspSvcFailed, + "Error occurs during\ + install osp service"); + } + + pclose(fd); + + _D("Widget Can be uninstalled. Pkgname : %s", m_context.tzPkgid.c_str()); + m_context.job->UpdateProgress(UninstallerContext::UNINSTALL_REMOVE_OSPSVC, + "Uninstall OSP service finished"); +} + +void TaskUninstallOspsvc::StartStep() +{ + LOGD("--------- : START ----------"); +} + +void TaskUninstallOspsvc::EndStep() +{ + LOGD("--------- : END ----------"); +} +} //namespace WidgetUninstall +} //namespace Jobs diff --git a/src_wearable/jobs/widget_uninstall/task_uninstall_ospsvc.h b/src_wearable/jobs/widget_uninstall/task_uninstall_ospsvc.h new file mode 100644 index 0000000..50ec347 --- /dev/null +++ b/src_wearable/jobs/widget_uninstall/task_uninstall_ospsvc.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file task_uninstall_ospsvc.h + * @author Pawel Sikorski(p.sikorski@samsung.com) + * @version 1.0 + * @brief Header file for widget uninstall task to uninstall ospsvc + */ + +#ifndef WRT_SRC_INSTALLER_CORE_JOB_WIDGET_UNINSTALL_TASK_UNINSTALL_OSPSVC_H +#define WRT_SRC_INSTALLER_CORE_JOB_WIDGET_UNINSTALL_TASK_UNINSTALL_OSPSVC_H + +#include + +struct UninstallerContext; //forward declaration + +namespace Jobs { +namespace WidgetUninstall { +class TaskUninstallOspsvc : + public DPL::TaskDecl +{ + private: + //context + UninstallerContext& m_context; + + //steps + void StepUninstallOspsvc(); + + void StartStep(); + void EndStep(); + + public: + TaskUninstallOspsvc(UninstallerContext& context); + virtual ~TaskUninstallOspsvc(); +}; +} //namespace WidgetUninstall +} //namespace Jobs + +#endif /* WRT_SRC_INSTALLER_CORE_JOB_WIDGET_UNINSTALL_TASK_UNINSTALL_OSPSVC_H */ diff --git a/src_wearable/jobs/widget_uninstall/uninstaller_context.h b/src_wearable/jobs/widget_uninstall/uninstaller_context.h new file mode 100755 index 0000000..ef1963f --- /dev/null +++ b/src_wearable/jobs/widget_uninstall/uninstaller_context.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file uninstaller_context.h + * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com) + * @version + * @brief Definition file of installer tasks data structures + */ + +#ifndef WRT_SRC_INSTALLER_CORE_UNINSTALLER_TASKS_UNINSTALLER_CONTEXT_H_ +#define WRT_SRC_INSTALLER_CORE_UNINSTALLER_TASKS_UNINSTALLER_CONTEXT_H_ + +#include +#include +#include +#include +#include +#include + +namespace Jobs { +namespace WidgetUninstall { +class JobWidgetUninstall; +} //namespace WidgetUninstall +} //namespace Jobs + +struct UninstallerContext +{ + enum UninstallStep + { + UNINSTALL_START, + UNINSTALL_PRECHECK, + UNINSTALL_REMOVE_WIDGETDIR, + UNINSTALL_REMOVE_DESKTOP, + UNINSTALL_REMOVE_FINISHED, + UNINSTALL_DB_UPDATE, + UNINSTALL_REMOVE_OSPSVC, + UNINSTALL_SMACK_DISABLE, + UNINSTALL_END + }; + + ///< flag that indicates whether installer starts + //to remove files.rStruct; + bool removeStarted; + ///< flag that indicates whether installer finishes + //to remove files completely. + bool removeFinished; + + boost::optional locations; + + UninstallStep uninstallStep; ///< current step of installation + Jobs::WidgetUninstall::JobWidgetUninstall *job; + std::list tzAppIdList; + std::string tzAppid; + std::string tzPkgid; + std::string tzServiceid; + bool removeAbnormal; + DPL::Utils::Path installedPath; + DPL::Utils::Path manifestFile; + WrtDB::AppType appType; +}; + +#endif // WRT_SRC_INSTALLER_CORE_UNINSTALLER_TASKS_UNINSTALLER_CONTEXT_H_ diff --git a/src_wearable/jobs/widget_uninstall/widget_uninstall_errors.h b/src_wearable/jobs/widget_uninstall/widget_uninstall_errors.h new file mode 100644 index 0000000..3c5970b --- /dev/null +++ b/src_wearable/jobs/widget_uninstall/widget_uninstall_errors.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file widget_uninstall_errors.h + * @author Pawel Sikorski (p.sikorski@samgsung.com) + * @version + * @brief + */ + +#ifndef WIDGET_UNINSTALL_ERRORS_H_ +#define WIDGET_UNINSTALL_ERRORS_H_ + +#include +#include + +using namespace Jobs::Exceptions; + +namespace Jobs { +namespace WidgetUninstall { +namespace Exceptions { + +DECLARE_JOB_EXCEPTION_BASE(JobExceptionBase, Base, ErrorUnknown) + +DECLARE_JOB_EXCEPTION(Base, DatabaseFailure, ErrorWidgetUninstallationFailed) +DECLARE_JOB_EXCEPTION(Base, AlreadyUninstalling, + ErrorWidgetUninstallationFailed) +DECLARE_JOB_EXCEPTION(Base, AppIsRunning, ErrorWidgetUninstallationFailed) +DECLARE_JOB_EXCEPTION(Base, WidgetNotExist, ErrorWidgetUninstallationFailed) +DECLARE_JOB_EXCEPTION(Base, UninstallOspSvcFailed, + ErrorWidgetUninstallationFailed) +DECLARE_JOB_EXCEPTION(Base, PlatformAPIFailure, ErrorWidgetUninstallationFailed) +DECLARE_JOB_EXCEPTION(Base, RemoveFileFailure, ErrorWidgetUninstallationFailed) +DECLARE_JOB_EXCEPTION(Base, Unremovable, ErrorWidgetUninstallationFailed) +DECLARE_JOB_EXCEPTION(Base, CheckMDMPolicyFailure, ErrorWidgetUninstallationFailed) +} //namespace +} //namespace +} //namespace + +#endif /* WIDGET_UNINSTALL_ERRORS_H_ */ diff --git a/src_wearable/jobs/widget_uninstall/widget_uninstaller_struct.h b/src_wearable/jobs/widget_uninstall/widget_uninstaller_struct.h new file mode 100644 index 0000000..3f33e4b --- /dev/null +++ b/src_wearable/jobs/widget_uninstall/widget_uninstaller_struct.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file widget_uninstaller_struct.h + * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com) + * @version 1.0 + * @brief Implementation file for widget installer struct + */ +#ifndef WRT_SRC_INSTALLER_CORE_UNINSTALLER_TASKS_WIDGET_INSTALLER_STRUCT_H_ +#define WRT_SRC_INSTALLER_CORE_UNINSTALLER_TASKS_WIDGET_INSTALLER_STRUCT_H_ + +//SYSTEM INCLUDES +#include + +//WRT INCLUDES +#include +#include +#include +#include +#include + +//Widget Uninstaller typedefs +typedef void (*UninstallerFinishedCallback)( + void *userParam, + std::string tizenId, + Jobs::Exceptions::Type); + +typedef void (*UninstallerProgressCallback)( + void *userParam, + ProgressPercent percent, + const ProgressDescription &description); + +//UninstallationStruct +typedef Jobs::JobCallbacksBase +WidgetUninstallCallbackBase; + +struct WidgetUninstallationStruct : public WidgetUninstallCallbackBase +{ + std::shared_ptr pkgmgrInterface; + + // It must be empty-constructible as a parameter of generic event + WidgetUninstallationStruct() + {} + + WidgetUninstallationStruct( + UninstallerFinishedCallback finished, + UninstallerProgressCallback progress, + void *param, + std::shared_ptr + _pkgmgrInterface + ) : + WidgetUninstallCallbackBase(finished, progress, param), + pkgmgrInterface(_pkgmgrInterface) + {} +}; +#endif // WRT_SRC_INSTALLER_CORE_UNINSTALLER_TASKS_WIDGET_INSTALLER_STRUCT_H_ diff --git a/src_wearable/logic/installer_controller.cpp b/src_wearable/logic/installer_controller.cpp new file mode 100644 index 0000000..d9b41d5 --- /dev/null +++ b/src_wearable/logic/installer_controller.cpp @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "installer_controller.h" +#include + +IMPLEMENT_SINGLETON(Logic::InstallerController) + +namespace Logic { +InstallerController::InstallerController() +{} + +void InstallerController::OnEventReceived( + const InstallerControllerEvents::InstallWidgetEvent &event) +{ + std::string fileName = event.GetArg0(); + std::string pkgId = event.GetArg1(); + Jobs::WidgetInstall::WidgetInstallationStruct installerStruct = event.GetArg2(); + m_installerLogic.InstallWidget(fileName, pkgId, installerStruct); +} + +void InstallerController::OnEventReceived( + const InstallerControllerEvents::InstallPluginEvent &event) +{ + std::string dirName = event.GetArg0(); + PluginInstallerStruct installerStruct = event.GetArg1(); + m_installerLogic.InstallPlugin(dirName, installerStruct); +} + +void InstallerController::OnEventReceived( + const InstallerControllerEvents::UninstallWidgetEvent &event) +{ + std::string widgetPkgName = event.GetArg0(); + WidgetUninstallationStruct uninstallerStruct = event.GetArg1(); + m_installerLogic.UninstallWidget(widgetPkgName, uninstallerStruct); +} + +Eina_Bool InstallerController::AddNextStep(void *data) +{ + Jobs::Job* model = static_cast(data); + CONTROLLER_POST_EVENT(InstallerController, + InstallerControllerEvents::NextStepEvent(model)); + + return ECORE_CALLBACK_CANCEL; +} + +void InstallerController::OnEventReceived( + const InstallerControllerEvents::NextStepEvent &event) +{ + Jobs::Job* model = event.GetArg0(); + Assert(model != NULL); + + if (m_installerLogic.NextStep(model)) { + ecore_idler_add(AddNextStep, model); + } +} + +void InstallerController::OnEventReceived( + const InstallerControllerEvents::InitializeEvent & /*event*/) +{ + m_installerLogic.Initialize(); +} + +void InstallerController::OnEventReceived( + const InstallerControllerEvents::TerminateEvent & /*event*/) +{ + m_installerLogic.Terminate(); +} +} //Logic + diff --git a/src_wearable/logic/installer_controller.h b/src_wearable/logic/installer_controller.h new file mode 100644 index 0000000..0cde86e --- /dev/null +++ b/src_wearable/logic/installer_controller.h @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef WRT_SRC_INSTALLER_CORE_INSTALLER_CONTROLLER_H_ +#define WRT_SRC_INSTALLER_CORE_INSTALLER_CONTROLLER_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * @brief holds events send to InstallControler + */ +namespace InstallerControllerEvents { +/** + * @brief Event for inicieting instalation process. + * + * This event holds std::string witch should be path to widget package + */ +DECLARE_GENERIC_EVENT_3(InstallWidgetEvent, + std::string, // zipFileName + std::string, // package id + Jobs::WidgetInstall::WidgetInstallationStruct) // installerStruct + +/** + * @brief Event for iniciating plugin instalation process. + * This event holds std::string witch should be path to plugin directory + * and PluginInstallerStruct which contain + * StatusCallack, progressCallback and private data for callbacks + */ +DECLARE_GENERIC_EVENT_2(InstallPluginEvent, std::string, PluginInstallerStruct) + +/** + * @brief Event for inicietig widget uninstallation. + * + * tizen id is used to point witch widget shuld be uninstalled + */ +DECLARE_GENERIC_EVENT_2(UninstallWidgetEvent, + std::string, + WidgetUninstallationStruct) + +/** + * @brief Event for pushing installation process forward. + */ +DECLARE_GENERIC_EVENT_1(NextStepEvent, Jobs::Job *) + +DECLARE_GENERIC_EVENT_0(InitializeEvent) +DECLARE_GENERIC_EVENT_0(TerminateEvent) +} // namespace InstallerEvents + +namespace Logic { +/** + * @brief Controls Widget installation + * + * Main Controler of wiget installation/uninstallation, this is also used + * for pushing forward each of processes. + * It waits for three events: + *
    + *
  • InstallWidgetEvent
  • + *
  • UninstallWidgetEvent
  • + *
  • NextStepEvent
  • + *
+ */ + +typedef DPL::TypeListDecl< + InstallerControllerEvents::InstallWidgetEvent, + InstallerControllerEvents::InstallPluginEvent, + InstallerControllerEvents::UninstallWidgetEvent, + InstallerControllerEvents::NextStepEvent, + InstallerControllerEvents::InitializeEvent, + InstallerControllerEvents::TerminateEvent>::Type +InstallerControllerEventsSet; + +class InstallerController : public DPL::Event::Controller< + InstallerControllerEventsSet> +{ + protected: + /** + * @brief Executed on InstallWidgetEvent received. + */ + virtual void OnEventReceived( + const InstallerControllerEvents::InstallWidgetEvent &event); + + /** + * @brief Executed on InstallPluginEvent received. + */ + virtual void OnEventReceived( + const InstallerControllerEvents::InstallPluginEvent &event); + + /** + * @brief Executed on UninstallWidgetEvent received. + */ + virtual void OnEventReceived( + const InstallerControllerEvents::UninstallWidgetEvent &event); + /** + * @brief Executed on NextStepEvent received. + */ + virtual void OnEventReceived( + const InstallerControllerEvents::NextStepEvent &event); + + virtual void OnEventReceived( + const InstallerControllerEvents::InitializeEvent &event); + virtual void OnEventReceived( + const InstallerControllerEvents::TerminateEvent &event); + + private: + // Embedded logic + Logic::InstallerLogic m_installerLogic; + + InstallerController(); + + static Eina_Bool AddNextStep(void *data); + + friend class DPL::Singleton; +}; + +typedef DPL::Singleton InstallerControllerSingleton; +} + +#endif // INSTALLER_CONTROLLER_H diff --git a/src_wearable/logic/installer_logic.cpp b/src_wearable/logic/installer_logic.cpp new file mode 100755 index 0000000..b80c98b --- /dev/null +++ b/src_wearable/logic/installer_logic.cpp @@ -0,0 +1,261 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace WrtDB; + +namespace Logic { +InstallerLogic::InstallerLogic() : + m_job(0), + m_NextHandle(0) +{} + +InstallerLogic::~InstallerLogic() +{ + if (m_job) { + delete m_job; + } +} + +void InstallerLogic::Initialize() +{ + _D("Done"); +} + +void InstallerLogic::Terminate() +{ + //TODO how to delete, if it is still running, paused and so on + if(m_job) + m_job->SetPaused(true); + + _D("Done"); +} + +Jobs::JobHandle InstallerLogic::AddAndStartJob() +{ + Jobs::JobHandle handle = GetNewJobHandle(); + m_job->SetJobHandle(handle); + //Start job + CONTROLLER_POST_EVENT(InstallerController, + InstallerControllerEvents::NextStepEvent(m_job)); + + return handle; +} + +//InstallWidget, UninstallWidget InstallPlugin method are almost the same +// But each Job has different constructor, so creating new Job is specific +Jobs::JobHandle InstallerLogic::InstallWidget( + const std::string & widgetPath, + const std::string & pkgId, + const Jobs::WidgetInstall::WidgetInstallationStruct & + installerStruct) +{ + if(m_job) + { + _E("Job is in progress. It is impossible to add new job"); + return -1; + } + + _D("New Widget Installation:"); + + m_job = new Jobs::WidgetInstall::JobWidgetInstall(widgetPath, pkgId, installerStruct); + + return AddAndStartJob(); +} + +Jobs::JobHandle InstallerLogic::UninstallWidget( + const std::string & widgetPkgName, + const + WidgetUninstallationStruct &uninstallerStruct) +{ + if(m_job) + { + _E("Job is in progress. It is impossible to add new job"); + return -1; + } + + _D("New Widget Uninstallation"); + + m_job = + new Jobs::WidgetUninstall::JobWidgetUninstall(widgetPkgName, + uninstallerStruct); + + return AddAndStartJob(); +} + +Jobs::JobHandle InstallerLogic::InstallPlugin( + std::string const & pluginPath, // TODO change type to PluginPath + const PluginInstallerStruct & + installerStruct) +{ + if(m_job) + { + _E("Job is in progress. It is impossible to add new job"); + return -1; + } + + _D("New Plugin Installation"); + + // TODO Conversion to PluginPath is temporary + m_job = + new Jobs::PluginInstall::JobPluginInstall(PluginPath(pluginPath), installerStruct); + + // before start install plugin, reset plugin data which is stopped + // during installing. (PluginDAO::INSTALLATION_IN_PROGRESS) + ResetProgressPlugins(); + + return AddAndStartJob(); +} + +#define TRANSLATE_JOB_EXCEPTION() \ + _rethrown_exception.getParam() +#define TRANSLATE_JOB_MESSAGE() \ + _rethrown_exception.GetMessage() + +bool InstallerLogic::NextStep(Jobs::Job *job) +{ + Try { + bool stepSucceded = job->NextStep(); + + job->SendProgress(); + + if (stepSucceded) { + return !job->IsPaused(); + } + + if (!job->GetAbortStarted()) { + //job successfully finished + + //send finished callback + job->SendFinishedSuccess(); + + switch (job->GetInstallationType()) { + case Jobs::PluginInstallation: + InstallWaitingPlugins(); + break; + default: //because of warning + break; + } + } else { + //job abort process completed + job->SendFinishedFailure(); + } + + //clean job + delete job; + m_job=0; + + return false; + } catch (Jobs::JobExceptionBase &exc) { + //start revert job + _D("Exception occured: %d. Reverting job...", exc.getParam()); + bool hasAbortSteps = job->Abort(); + job->SetAbortStarted(true); + job->SaveExceptionData(exc); + + if (!hasAbortSteps) { + //no AbortSteps + job->SendFinishedFailure(); + + //clean job + delete job; + m_job=0; + } + return hasAbortSteps; + } +} + +//TODO implement me +bool InstallerLogic::AbortJob(const Jobs::JobHandle & /*handle*/) +{ + _W("Not implemented"); + return true; +} +void InstallerLogic::InstallWaitingPlugins() +{ + PluginHandleSetPtr waitingPlugins; + + waitingPlugins = + PluginDAO::getPluginHandleByStatus(PluginDAO::INSTALLATION_WAITING); + + FOREACH(it, *waitingPlugins) + { + resolvePluginDependencies(*it); + } +} + +void InstallerLogic::ResetProgressPlugins() +{ + PluginHandleSetPtr progressPlugins; + + progressPlugins = + PluginDAO::getPluginHandleByStatus(PluginDAO::INSTALLATION_IN_PROGRESS); + + FOREACH(it, *progressPlugins) { + FeatureHandleListPtr featureListPtr = + FeatureDAOReadOnly::GetFeatureHandleListForPlugin(*it); + FOREACH(ItFeature, *featureListPtr) { + FeatureDAO::UnregisterFeature(*ItFeature); + } + PluginDAO::unregisterPlugin(*it); + } +} + +bool InstallerLogic::resolvePluginDependencies(PluginHandle handle) +{ + PluginHandleSetPtr dependencies(new PluginHandleSet); + + PluginObjects::ObjectsPtr requiredObjects = + PluginDAO::getRequiredObjectsForPluginHandle(handle); + + PluginHandle depHandle = + Jobs::PluginInstall::JobPluginInstall::INVALID_HANDLE; + + FOREACH(requiredObject, *requiredObjects) + { + depHandle = + PluginDAO::getPluginHandleForImplementedObject(*requiredObject); + + if (depHandle == + Jobs::PluginInstall::JobPluginInstall::INVALID_HANDLE) + { + _E("Library implementing: %s NOT FOUND", (*requiredObject).c_str()); + + //PluginDAO::SetPluginInstallationStatus(INSTALLATION_WAITING); + return false; + } + dependencies->insert(depHandle); + } + + PluginDAO::registerPluginLibrariesDependencies(handle, dependencies); + PluginDAO::setPluginInstallationStatus(handle, + PluginDAO::INSTALLATION_COMPLETED); + + return true; +} +} + diff --git a/src_wearable/logic/installer_logic.h b/src_wearable/logic/installer_logic.h new file mode 100755 index 0000000..3e87a44 --- /dev/null +++ b/src_wearable/logic/installer_logic.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef WRT_SRC_INSTALLER_CORE_INSTALLER_LOGIC_H_ +#define WRT_SRC_INSTALLER_CORE_INSTALLER_LOGIC_H_ + +#include +#include +#include +#include +#include +#include + +namespace Logic { +class InstallerLogic +{ + Jobs::Job* m_job; + + void ResetProgressPlugins(); + void InstallWaitingPlugins(); + bool resolvePluginDependencies(PluginHandle handle); + + Jobs::JobHandle m_NextHandle; + Jobs::JobHandle GetNewJobHandle() + { + return m_NextHandle++; + } + Jobs::JobHandle AddAndStartJob(); + + public: + virtual ~InstallerLogic(); + + void Initialize(); + + void Terminate(); + + Jobs::JobHandle InstallWidget( + const std::string & widgetPath, + const std::string & pkgId, + const Jobs::WidgetInstall::WidgetInstallationStruct & + installerStruct); + + Jobs::JobHandle UninstallWidget( + const std::string & widgetPkgName, + const WidgetUninstallationStruct & + uninstallerStruct); + + Jobs::JobHandle InstallPlugin(std::string const & pluginPath, + const PluginInstallerStruct &installerStruct); + + bool NextStep(Jobs::Job* installModel); + + bool AbortJob(const Jobs::JobHandle &handle); + + private: + InstallerLogic(); + + friend class InstallerController; +}; +} + +#endif // INSTALLER_LOGIC_H diff --git a/src_wearable/misc/feature_logic.cpp b/src_wearable/misc/feature_logic.cpp new file mode 100755 index 0000000..9c1c9ee --- /dev/null +++ b/src_wearable/misc/feature_logic.cpp @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "feature_logic.h" + +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace Jobs { +namespace WidgetInstall { +namespace { +const DPL::String PRIVILEGE_TESTAUTOMATION = + L"http://tizen.org/privilege/testautomation"; +const DPL::String DEVICE_CAPABILITY_TESTAUTOMATION = L"testautomation"; +} +FeatureLogic::FeatureLogic(const WrtDB::TizenAppId & tzAppid) : + m_rejected(false) +{ + WrtDB::WidgetDAOReadOnly widgetDao(tzAppid); + WidgetFeatureSet featureSet = widgetDao.getFeaturesList(); + FOREACH(it, featureSet) { + _D("Feature name : %ls", it->name.c_str()); + WrtDB::DeviceCapabilitySet dcs; + if (!DPL::StringCompare(it->name, PRIVILEGE_TESTAUTOMATION)) { + // special privilege + // This privilege doesn't have plugin in the target + // only use to special behavior + dcs.insert(DEVICE_CAPABILITY_TESTAUTOMATION); + } else { + // normal privilege + dcs = WrtDB::FeatureDAOReadOnly::GetDeviceCapability(it->name); + } + FOREACH(devCap, dcs) { + _D("--- dev cap : %ls", (*devCap).c_str()); + } + Feature feature(*it, dcs); + m_featureList.push_back(feature); + } + m_currentFeature = m_featureList.begin(); + + // ok we must set iterator on the first processable node + if (!isProcessable()) { + next(); + } +} + +bool FeatureLogic::isDone() const +{ + return m_currentFeature == m_featureList.end(); +} + +bool FeatureLogic::next() +{ + while (!isDone()) { + if (m_currentFeature->currentCap != + m_currentFeature->devCapSet.end()) + { + m_currentFeature->currentCap++; + } else { + ++m_currentFeature; + } + // we moved pointer + if (isProcessable()) { + return true; + } + } + return false; +} + +void FeatureLogic::setAceResponse(bool allowed) +{ + AssertMsg(isProcessable(), "Wrong usage"); + if (!allowed) { + m_currentFeature->rejected = true; + m_rejected = true; + } +} + +DPL::String FeatureLogic::getDevice() const +{ + return *(m_currentFeature->currentCap); +} + +bool FeatureLogic::isProcessable() const +{ + if (isDone()) { + return false; + } + + if (m_currentFeature->currentCap == m_currentFeature->devCapSet.end()) { + return false; + } + + return true; +} +} // namespace WidgetInstall +} // namespace Jobs + diff --git a/src_wearable/misc/feature_logic.h b/src_wearable/misc/feature_logic.h new file mode 100644 index 0000000..d407cb0 --- /dev/null +++ b/src_wearable/misc/feature_logic.h @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SRC_INSTALLER_MISC_FEATURE_LOGIC +#define SRC_INSTALLER_MISC_FEATURE_LOGIC + +#include +#include + +#include +#include +#include + +#include +#include + +namespace Jobs { +namespace WidgetInstall { +class FeatureLogic : DPL::Noncopyable +{ + public: + + FeatureLogic(const WrtDB::TizenAppId & tzAppid); + + bool isDone() const; + + bool next(); + + void setAceResponse(bool allowed); + + DPL::String getDevice() const; + + bool isRejected(void) const + { + return m_rejected; + } + + struct Feature : public WidgetFeature { + WrtDB::DeviceCapabilitySet devCapSet; + WrtDB::DeviceCapabilitySet::const_iterator currentCap; + + Feature(const WidgetFeature &wf, + const WrtDB::DeviceCapabilitySet &set) : + WidgetFeature(wf) + , devCapSet(set) + { + currentCap = devCapSet.begin(); + } + + explicit Feature(const Feature &second) : WidgetFeature(second) + { + devCapSet = second.devCapSet; + currentCap = devCapSet.find(*second.currentCap); + rejected = second.rejected; + } + + private: + void operator=(const Feature &second) + { + name = second.name; + devCapSet = second.devCapSet; + rejected = second.rejected; + pluginId = second.pluginId; + currentCap = devCapSet.find(*second.currentCap); + } + }; + + typedef std::list FeatureList; + typedef FeatureList::const_iterator FeatureIterator; + + FeatureIterator resultBegin() + { + return m_featureList.begin(); + } + FeatureIterator resultEnd() + { + return m_featureList.end(); + } + + private: + bool isProcessable() const; + + FeatureList m_featureList; + FeatureList::iterator m_currentFeature; + bool m_rejected; +}; + +typedef std::shared_ptr FeatureLogicPtr; +} // namespace WidgetInstall +} // namespace Jobs + +#endif // SRC_INSTALLER_MISC_FEATURE_LOGIC diff --git a/src_wearable/misc/libxml_utils.cpp b/src_wearable/misc/libxml_utils.cpp new file mode 100644 index 0000000..114e95b --- /dev/null +++ b/src_wearable/misc/libxml_utils.cpp @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file libxml_utils.cpp + * @author Tomasz Iwanek (t.iwanek@samsung.com) + */ + +#include "libxml_utils.h" + +#include +#include + +IMPLEMENT_SINGLETON(LibxmlUtils) + +LibxmlUtils::LibxmlUtils() : isInitialized(false) +{} + +LibxmlUtils::~LibxmlUtils() +{ + if (isInitialized) { + _D("Libxml - cleaning"); + // Cleanup function for the XML library. + xmlCleanupParser(); + //this is to debug memory for regression tests + xmlMemoryDump(); + } +} + +void LibxmlUtils::init() +{ + if (!isInitialized) { + LIBXML_TEST_VERSION + isInitialized = true; + _D("Libxml have been initialized"); + } + _D("Libxml already initialized"); +} + diff --git a/src_wearable/misc/libxml_utils.h b/src_wearable/misc/libxml_utils.h new file mode 100644 index 0000000..5354bda --- /dev/null +++ b/src_wearable/misc/libxml_utils.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file libxml_utils.h + * @author Tomasz Iwanek (t.iwanek@samsung.com) + */ + +#ifndef LIBXML_UTILS_H +#define LIBXML_UTILS_H + +#include +#include + +#include +#include +#include +#include + +/** + * @brief The LibxmlUtils class + * + * Singleton for assurence for libxml2 initialization + * + * Use: LibxmlUtils::Instance().init(); to initialize library + * + */ +class LibxmlUtils +{ + public: + DECLARE_EXCEPTION_TYPE(DPL::Exception, Base) + DECLARE_EXCEPTION_TYPE(Base, Libxml2Error) + + LibxmlUtils(); + ~LibxmlUtils(); + + void init(); + + private: + bool isInitialized; + + friend class DPL::Singleton; +}; + +typedef DPL::Singleton LibxmlSingleton; + +#endif // LIBXML_UTILS_H diff --git a/src_wearable/misc/plugin_path.cpp b/src_wearable/misc/plugin_path.cpp new file mode 100644 index 0000000..2b2ebdb --- /dev/null +++ b/src_wearable/misc/plugin_path.cpp @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file plugin_path_builder.cpp + * @author Kamil Nować (k.nowac@partner.samgsung.com) + * @version + * @brief + */ + +#include +#include +#include + +using namespace DPL::Utils; + +PluginPath::PluginPath(const Path& fullPath) : Path(fullPath.Fullpath()) +{ + setLibraryCombinedName( + WrtDB::GlobalConfig::GetPluginPrefix(), + WrtDB::GlobalConfig::GetPluginSuffix()); +}; +PluginPath::PluginPath(const std::string& fullPath) : Path(fullPath) +{ + setLibraryCombinedName( + WrtDB::GlobalConfig::GetPluginPrefix(), + WrtDB::GlobalConfig::GetPluginSuffix()); +}; +PluginPath::PluginPath(const DPL::String& fullPath) : Path(fullPath) +{ + setLibraryCombinedName( + WrtDB::GlobalConfig::GetPluginPrefix(), + WrtDB::GlobalConfig::GetPluginSuffix()); +}; +PluginPath::PluginPath(){} + +PluginPath PluginPath::getMetaFile() const +{ + PluginPath metaFile = *this; + return metaFile /= WrtDB::GlobalConfig::GetPluginMetafileName(); +} \ No newline at end of file diff --git a/src_wearable/misc/plugin_path.h b/src_wearable/misc/plugin_path.h new file mode 100644 index 0000000..8ada790 --- /dev/null +++ b/src_wearable/misc/plugin_path.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file plugin_path_builder.cpp + * @author Kamil Nować (k.nowac@partner.samgsung.com) + * @version + * @brief + */ + +#ifndef PLUGIN_PATH_H +#define PLUGIN_PATH_H + +#include +#include +#include + +class PluginPath: public DPL::Utils::Path{ +private: + std::string m_library; + +public: + PluginPath(const DPL::Utils::Path& fullPath); + PluginPath(const std::string& fullPath); + PluginPath(const DPL::String& fullPath); + PluginPath(); + + //getMetafile() this function adds metafile to current path. + PluginPath getMetaFile() const; + + //setLibraryCombinedName This function creates name for library by adding + //prefix and suffix to PluginPath object filename. + void setLibraryCombinedName(const std::string& prefix, const std::string& sufix) + { + this->m_library = prefix + this->Filename() + sufix; + } + + //getLibraryName returns library name + const std::string& getLibraryName() const + { + return m_library; + } + //getLibraryPath returns full path to the library + const PluginPath getLibraryPath() const + { + return this->operator /(m_library); + } +}; + +#endif // PLUGIN_PATH_H diff --git a/src_wearable/misc/wac_widget_id.cpp b/src_wearable/misc/wac_widget_id.cpp new file mode 100644 index 0000000..dca752b --- /dev/null +++ b/src_wearable/misc/wac_widget_id.cpp @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file + * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com) + * @version 1.0 + * @brief + */ +#include "wac_widget_id.h" + +#include +#include + +#include + +#include +#include + +namespace { +const char *SCHEME_HTTP = "http"; +const char *SCHEME_HTTPS = "https"; +} + +WacWidgetId::WacWidgetId(const DPL::OptionalString &widgetId) : + m_schemaMatch(false) +{ + if (!!widgetId) { + std::string wid = DPL::ToUTF8String(*widgetId); + parse(wid.c_str()); + } +} + +bool WacWidgetId::matchHost(const DPL::String &second) const +{ + _D("m_schemaMatch is: %d", m_schemaMatch); + if (!m_schemaMatch) { + return false; + } + + _D("Matching DNS identity: %s %ls", m_host.c_str(), second.c_str()); + + return m_host == DPL::ToUTF8String(second); +} + +void WacWidgetId::parse(const char *url) +{ + _D("Widget id to parse: %s", url); + + std::unique_ptr > + iri(iri_parse(url), iri_destroy); + + if (!iri.get()) { + _E("Error in parsing widget id."); + return; // m_schemaMatch == false; + } + + std::string scheme; + + if (iri.get()->scheme) { + scheme = iri.get()->scheme; + } else { + _W("Error. No scheme in widget id."); + return; // m_schemaMatch == false; + } + + // should we support HTTP and HTTPS? wac says nothing + // std::transform(m_scheme.begin(), m_scheme.end(), m_scheme.begin(), + // tolower); + + // We only match "http" and "https" schemas + if ((scheme != SCHEME_HTTP) && (scheme != SCHEME_HTTPS)) { + _W("Unknown scheme in widget id. %s", scheme.c_str()); + return; // m_schemaMatch == false; + } else { + m_schemaMatch = true; + } + + if (iri.get()->host) { + m_host = iri.get()->host; + _D("Host has been set to: %s", m_host.c_str()); + } + + // What to do when host is empty? No info in wac documentation. + + // Any post processing algorithm? No info in wac documentation. +} diff --git a/src_wearable/misc/wac_widget_id.h b/src_wearable/misc/wac_widget_id.h new file mode 100644 index 0000000..dba5f36 --- /dev/null +++ b/src_wearable/misc/wac_widget_id.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file + * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com) + * @version 1.0 + * @brief + */ +#ifndef WRT_ENGINE_SRC_INSTALLER_CORE_MISC_WAC_WIDGET_ID_H +#define WRT_ENGINE_SRC_INSTALLER_CORE_MISC_WAC_WIDGET_ID_H + +#include +#include + +class WacWidgetId +{ + public: + explicit WacWidgetId(const DPL::OptionalString &widgetId); + bool matchHost(const DPL::String &second) const; + + private: + void parse(const char *url); + + bool m_schemaMatch; + std::string m_host; +}; + +#endif // WRT_ENGINE_SRC_INSTALLER_CORE_MISC_WAC_WIDGET_ID_H + diff --git a/src_wearable/misc/widget_install_to_external.cpp b/src_wearable/misc/widget_install_to_external.cpp new file mode 100644 index 0000000..b0219dd --- /dev/null +++ b/src_wearable/misc/widget_install_to_external.cpp @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file widget_install_to_external.cpp + * @author Soyoung Kim (sy037.kim@smasung.com) + */ +#include "widget_install_to_external.h" + +#include +#include +#include + +IMPLEMENT_SAFE_SINGLETON(WidgetInstallToExt) + +WidgetInstallToExt::WidgetInstallToExt() : + m_handle(NULL), + m_appId("") +{} + +WidgetInstallToExt::~WidgetInstallToExt() +{} + +void WidgetInstallToExt::initialize(std::string appId) +{ + _D("WidgetInstallToExt::initialize()"); + m_appId = appId; + + if (NULL == m_handle) { + m_handle = app2ext_init(APP2EXT_SD_CARD); + if (NULL == m_handle) { + ThrowMsg(Exception::ErrorInstallToExt, "initialize failed"); + } + } +} + +void WidgetInstallToExt::deinitialize() +{ + _D("WidgetInstallToExt::deinitialize()"); + if (NULL != m_handle) { + if (0 < app2ext_deinit(m_handle)) { + ThrowMsg(Exception::ErrorInstallToExt, + "app2ext deinitialize \ + failed"); + } + } +} + +void WidgetInstallToExt::preInstallation(GList *dirList, int dSize) +{ + _D("WidgetInstallToExt::preInstallation()"); + Assert(m_handle); + + int ret = m_handle->interface.pre_install(m_appId.c_str(), dirList, dSize); + + if (APP2EXT_SUCCESS == ret) { + _D("App2Ext pre install success"); + } else { + postInstallation(false); + ThrowMsg(Exception::ErrorInstallToExt, "pre-install failed"); + } +} + +void WidgetInstallToExt::postInstallation(bool status) +{ + _D("WidgetInstallToExt::postInstallation()"); + + if (NULL != m_handle) { + if (status) { + m_handle->interface.post_install(m_appId.c_str(), + APP2EXT_STATUS_SUCCESS); + } else { + m_handle->interface.post_install(m_appId.c_str(), + APP2EXT_STATUS_FAILED); + } + } +} + +void WidgetInstallToExt::preUpgrade(GList *dirList, int dSize) +{ + _D("WidgetInstallToExt::preUpgrade()"); + Assert(m_handle); + + int ret = m_handle->interface.pre_upgrade(m_appId.c_str(), dirList, dSize); + if (APP2EXT_SUCCESS == ret) { + _D("App2Ext pre-upgrade success"); + } else { + postUpgrade(false); + ThrowMsg(Exception::ErrorInstallToExt, "pre-upgrade failed"); + } +} + +void WidgetInstallToExt::postUpgrade(bool status) +{ + _D("WidgetInstallToExt::postUpgrade()"); + if (NULL != m_handle) { + if (status) { + m_handle->interface.post_upgrade(m_appId.c_str(), + APP2EXT_STATUS_SUCCESS); + } else { + m_handle->interface.post_upgrade(m_appId.c_str(), + APP2EXT_STATUS_FAILED); + } + } +} + +void WidgetInstallToExt::uninstallation() +{ + _D("WidgetInstallToExt::uninstallation()"); + + Assert(m_handle); + + int ret = m_handle->interface.pre_uninstall(m_appId.c_str()); + if (APP2EXT_SUCCESS == ret) { + if (APP2EXT_SUCCESS == + m_handle->interface.post_uninstall(m_appId.c_str())) + { + _D("App2Ext pre-uninstall success"); + } else { + ThrowMsg(Exception::ErrorInstallToExt, "post-uninstall failed"); + } + } else { + ThrowMsg(Exception::ErrorInstallToExt, "pre-uninstall failed"); + } +} + +void WidgetInstallToExt::disable() +{ + _D("WidgetInstallToExt::disable()"); + if (NULL != m_handle) { + int ret = m_handle->interface.disable(m_appId.c_str()); + if (APP2EXT_SUCCESS != ret && APP2EXT_ERROR_UNMOUNT != ret) { + ThrowMsg(Exception::ErrorInstallToExt, "disable failed"); + } + } +} diff --git a/src_wearable/misc/widget_install_to_external.h b/src_wearable/misc/widget_install_to_external.h new file mode 100644 index 0000000..cc9c4df --- /dev/null +++ b/src_wearable/misc/widget_install_to_external.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file widget_install_to_external.h + * @author Soyoung Kim (sy037.kim@smasung.com) + */ +#ifndef WRT_INSTALLER_SRC_MISC_WIDGET_INSTALL_TO_EXTERNAL_H +#define WRT_INSTALLER_SRC_MISC_WIDGET_INSTALL_TO_EXTERNAL_H + +#include +#include +#include +#include + +class WidgetInstallToExt +{ + public: + class Exception + { + public: + DECLARE_EXCEPTION_TYPE(DPL::Exception, Base) + DECLARE_EXCEPTION_TYPE(Base, ErrorInstallToExt) + }; + + void initialize(std::string appId); + void deinitialize(); + void preInstallation(GList* dirList, int dSize); + void postInstallation(bool status); + void preUpgrade(GList* dirList, int dSize); + void postUpgrade(bool status); + void uninstallation(); + void disable(); + + private: + app2ext_handle *m_handle; + std::string m_appId; + + WidgetInstallToExt(); + ~WidgetInstallToExt(); + + friend class DPL::Singleton; +}; + +typedef DPL::Singleton WidgetInstallToExtSingleton; + +#endif // WRT_INSTALLER_SRC_MISC_WIDGET_INSTALL_TO_EXTERNAL_H diff --git a/src_wearable/misc/widget_location.cpp b/src_wearable/misc/widget_location.cpp new file mode 100755 index 0000000..00f1037 --- /dev/null +++ b/src_wearable/misc/widget_location.cpp @@ -0,0 +1,290 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file widget_location.cpp + * @author Iwanek Tomasz (t.iwanek@smasung.com) + */ +#include "widget_location.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +WidgetLocation::DirectoryDeletor::DirectoryDeletor(bool isReadOnly) : + m_dirpath(Jobs::WidgetInstall::createTempPath(isReadOnly)) +{} + +WidgetLocation::DirectoryDeletor::DirectoryDeletor(std::string tempPath) : + m_dirpath(tempPath) +{} + +WidgetLocation::DirectoryDeletor::~DirectoryDeletor() +{ + _D("Removing widget installation temporary directory: %s", m_dirpath.c_str()); + std::string roPath = WrtDB::GlobalConfig::GetUserPreloadedWidgetPath(); + + if (0 != m_dirpath.compare(0, roPath.length(), roPath)) { + if (!WrtUtilRemove(m_dirpath)) { + _W("Fail at removing directory: %s", m_dirpath.c_str()); + } + } +} + +std::string WidgetLocation::DirectoryDeletor::getTempPath() const +{ + return m_dirpath; +} + +WidgetLocation::WidgetLocation() : + m_temp(new WidgetLocation::DirectoryDeletor(true)) +{} + +WidgetLocation::WidgetLocation(const std::string & widgetname) : + m_pkgid(widgetname), + m_temp(new WidgetLocation::DirectoryDeletor(false)) +{} + +WidgetLocation::~WidgetLocation() +{} + +WidgetLocation::WidgetLocation(const std::string & widgetname, + std::string sourcePath, + WrtDB::PackagingType t, + bool isReadonly, + InstallMode::ExtensionType eType) : + m_pkgid(widgetname), + m_widgetSource(sourcePath), + m_type(t), + m_temp( + new WidgetLocation::DirectoryDeletor(isReadonly)), + m_extensionType(eType) +{ + if (isReadonly) { + m_installedPath += WrtDB::GlobalConfig::GetUserPreloadedWidgetPath(); + } else { + m_installedPath += WrtDB::GlobalConfig::GetUserInstalledWidgetPath(); + } + if (access(m_widgetSource.c_str(), F_OK) != 0) { + m_widgetSource = m_installedPath + "/" + m_pkgid; + } +} + +WidgetLocation::WidgetLocation(const std::string & widgetname, + std::string sourcePath, + std::string dirPath, + WrtDB::PackagingType t, + bool isReadonly, + InstallMode::ExtensionType eType) : + m_pkgid(widgetname), + m_widgetSource(sourcePath), + m_type(t), + m_temp(new WidgetLocation::DirectoryDeletor(dirPath)), + m_extensionType(eType) +{ + if (isReadonly) { + m_installedPath += WrtDB::GlobalConfig::GetUserPreloadedWidgetPath(); + } else { + m_installedPath += WrtDB::GlobalConfig::GetUserInstalledWidgetPath(); + } + if (access(m_widgetSource.c_str(), F_OK) != 0) { + m_widgetSource = m_installedPath + "/" + m_pkgid; + } +} + +// TODO cache all these paths +std::string WidgetLocation::getInstallationDir() const +{ + return m_installedPath; +} + +std::string WidgetLocation::getPackageInstallationDir() const +{ + return m_installedPath + "/" + m_pkgid; +} + +std::string WidgetLocation::getSourceDir() const +{ + return m_installedPath + "/" + + m_pkgid + WrtDB::GlobalConfig::GetWidgetSrcPath(); +} + +std::string WidgetLocation::getBinaryDir() const +{ + return m_installedPath + "/" + + m_pkgid + WrtDB::GlobalConfig::GetUserWidgetExecPath(); +} + +std::string WidgetLocation::getUserBinaryDir() const +{ + return getUserDataRootDir() + "/" + + WrtDB::GlobalConfig::GetUserWidgetExecPath(); +} + +std::string WidgetLocation::getExecFile() const +{ + return getBinaryDir() + "/" + m_appid; +} + +std::string WidgetLocation::getBackupDir() const +{ + return getPackageInstallationDir() + ".backup"; +} + +std::string WidgetLocation::getBackupSourceDir() const +{ + return getBackupDir() + WrtDB::GlobalConfig::GetWidgetSrcPath(); +} + +std::string WidgetLocation::getBackupBinaryDir() const +{ + return getBackupDir() + WrtDB::GlobalConfig::GetUserWidgetExecPath(); +} + +std::string WidgetLocation::getBackupExecFile() const +{ + return getBackupBinaryDir() + "/" + m_appid; +} + +std::string WidgetLocation::getBackupPrivateDir() const +{ + return getBackupDir() + "/" + + WrtDB::GlobalConfig::GetWidgetPrivateStoragePath(); +} + +std::string WidgetLocation::getUserDataRootDir() const +{ + return std::string(WrtDB::GlobalConfig::GetWidgetUserDataPath()) + + "/" + m_pkgid; +} + +std::string WidgetLocation::getPrivateStorageDir() const +{ + return getUserDataRootDir() + "/" + + WrtDB::GlobalConfig::GetWidgetPrivateStoragePath(); +} + +std::string WidgetLocation::getPrivateTempStorageDir() const +{ + return getUserDataRootDir() + "/" + + WrtDB::GlobalConfig::GetWidgetPrivateTempStoragePath(); +} + + +std::string WidgetLocation::getTemporaryPackageDir() const +{ + return m_temp->getTempPath(); +} + +std::string WidgetLocation::getTemporaryRootDir() const +{ + if (m_extensionType == InstallMode::ExtensionType::DIR) { + return getWidgetSource() + WrtDB::GlobalConfig::GetWidgetSrcPath(); + } + return getSourceDir(); +} + +DPL::String WidgetLocation::getPkgId() const +{ + return DPL::FromUTF8String(m_pkgid); +} + +std::string WidgetLocation::getInstalledIconPath() const +{ + return m_iconPath; +} + +std::string WidgetLocation::getWidgetSource() const +{ + return m_widgetSource; +} + +void WidgetLocation::setIconTargetFilenameForLocale(const std::string & icon) +{ + m_iconPath = icon; +} + +void WidgetLocation::registerExternalLocation(const std::string & file) +{ + m_externals.push_back(file); +} + +WrtDB::ExternalLocationList WidgetLocation::listExternalLocations() const +{ + return m_externals; +} + +void WidgetLocation::registerAppid(const std::string & appid) +{ + m_appid = appid; +} + +#ifdef SERVICE_ENABLED +void WidgetLocation::registerServiceAppid(const std::string & svcAppid) +{ + m_svcAppid = svcAppid; +} +#endif + +std::string WidgetLocation::getSharedRootDir() const +{ + /* TODO : add wrt-commons*/ + return getUserDataRootDir() + "/shared"; +} + +std::string WidgetLocation::getSharedResourceDir() const +{ + return getSharedRootDir() + "/res"; +} + +std::string WidgetLocation::getSharedDataDir() const +{ + return getSharedRootDir() + "/data"; +} + +std::string WidgetLocation::getSharedTrustedDir() const +{ + return getSharedRootDir() + "/trusted"; +} + +std::string WidgetLocation::getBackupSharedDir() const +{ + return getBackupDir() + "/shared"; +} + +std::string WidgetLocation::getBackupSharedDataDir() const +{ + return getBackupSharedDir() + "/data"; +} + +std::string WidgetLocation::getBackupSharedTrustedDir() const +{ + return getBackupSharedDir() + "/trusted"; +} + +std::string WidgetLocation::getNPPluginsExecFile() const +{ + return getBinaryDir() + "/" + m_appid + ".npruntime"; +} + +std::string WidgetLocation::getNPPluginsDir() const +{ + return getSourceDir() + "/plugins"; +} diff --git a/src_wearable/misc/widget_location.h b/src_wearable/misc/widget_location.h new file mode 100755 index 0000000..f7fd546 --- /dev/null +++ b/src_wearable/misc/widget_location.h @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file widget_location.h + * @author Iwanek Tomasz (t.iwanek@smasung.com) + */ +#ifndef WRT_INSTALLER_SRC_MISC_WIDGET_LOCATION_H +#define WRT_INSTALLER_SRC_MISC_WIDGET_LOCATION_H + +#include +#include + +#include +#include +#include +#include + +/** + * @brief The WidgetLocation class + * + * Object that stores locations of several files/directories according + * to package name + * + * Current package layout (of installed package) is following: + * + * /opt/apps/[package_name] + * \_____________ /data + * \_____________ /share + * \_____________ /bin + * \_____________ /bin/[id_of_installed_package] + * \_____________ /res/wgt/ + * \___ config.xml + * \___ [widgets_archive_content] + * + * 1) Normal Widget + * Developer provides content of res/wgt directory (package contains that + * directory as root). + * + * 2) For OSP Service Hybrid App is actually a bit different: + * Root is OSP Service directory, WebApp content is located in [root]/res/wgt + * + * Temporary directory is directory when widget is placed at the begining + * of installation process. After parsing process of config.xml, destination + * directory is created. + */ +class WidgetLocation +{ + class DirectoryDeletor + { + public: + DirectoryDeletor(); + DirectoryDeletor(std::string tempPath); + DirectoryDeletor(bool isPreload); + + ~DirectoryDeletor(); + std::string getTempPath() const; + + private: + std::string m_dirpath; + }; + + public: + DECLARE_EXCEPTION_TYPE(DPL::Exception, Base) + DECLARE_EXCEPTION_TYPE(Base, NoTemporaryPath) + /** + * @brief WidgetLocation + * + * Creates useless object. Needed by optional type + */ + WidgetLocation(); + /** + * @brief WidgetLocation Builds paths for widget location during + * uninstallation + * + * Uninstallation process needs only installed package directory. + * + * @param widgetname name of widget + */ + explicit WidgetLocation(const std::string & widgetname); + /** + * @brief WidgetLocation Builds paths for widget location during + * installation + * + * @param widgetname name of widget + * @param sourcePath given source path + * @param t declaraced type of widget if type is needed + * + * In destruction removes temporary directory + */ + WidgetLocation(const std::string & widgetname, std::string sourcePath, + WrtDB::PackagingType t = WrtDB::PKG_TYPE_NOMAL_WEB_APP, + bool isReadonly = false, + InstallMode::ExtensionType eType = + InstallMode::ExtensionType::WGT); + + WidgetLocation(const std::string & widgetname, std::string sourcePath, + std::string dirPath, + WrtDB::PackagingType t = WrtDB::PKG_TYPE_NOMAL_WEB_APP, + bool isReadonly = false, + InstallMode::ExtensionType eType = + InstallMode::ExtensionType::WGT); + + ~WidgetLocation(); + + // Installed paths + std::string getInstallationDir() const; // /opt/apps or /usr/apps + std::string getPackageInstallationDir() const; // /opt/apps/[package] + std::string getSourceDir() const; // /opt/apps/[package]/res/wgt + std::string getBinaryDir() const; // /opt/apps/[package]/bin or /usr/apps/[package]/bin + std::string getUserBinaryDir() const; // /opt/apps/[package]/bin + std::string getExecFile() const; // /opt/apps/[package]/bin/[package] + std::string getBackupDir() const; // /opt/apps/[package].backup + std::string getBackupSourceDir() const; // /opt/apps/[pkg].backup/res/wgt + std::string getBackupBinaryDir() const; // /opt/apps/[pkg].backup/bin + std::string getBackupExecFile() const; // /opt/apps/[pkg].backup/bin/[pkg] + std::string getBackupPrivateDir() const; // /opt/apps/[pkg].backup/data + std::string getUserDataRootDir() const; // /opt/usr/apps/[package] + std::string getPrivateStorageDir() const; // /opt/usr/apps/[package]/data + std::string getPrivateTempStorageDir() const; // /opt/usr/apps/[package]/tmp + std::string getSharedRootDir() const; // /opt/usr/apps/[package]/shared + std::string getSharedResourceDir() const; // /opt/usr/apps/[package]/shared/res + std::string getSharedDataDir() const; // /opt/usr/apps/[package]/shared/data + std::string getSharedTrustedDir() const; // /opt/usr/apps/[package]/shared/trusted + std::string getBackupSharedDir() const; // /opt/usr/apps/[package].backup/shared + std::string getBackupSharedDataDir() const; // /opt/usr/apps/[package].backup/shared/data + std::string getBackupSharedTrustedDir() const; // /opt/usr/apps/[package].backup/shared/trusted + std::string getNPPluginsDir() const; // /opt/usr/apps/[package]/res/wgt/plugins + std::string getNPPluginsExecFile() const; // /opt/usr/apps/[package]/bin/{execfile} + + // Temporary paths + /** + * @brief getTemporaryRootDir + * @return value of root for developer's provide package (root of unpacked + * .wgt file) + */ + std::string getTemporaryPackageDir() const; + /** + * @brief getTemporaryRootDir + * + * Value of this will differs according to type of installed widget. + * + * @return value of root for content in temporary directory to be copied + * into 'res/wgt' + */ + std::string getTemporaryRootDir() const; + + //icons + /** + * @brief setIconTargetFilenameForLocale set installed ion path according to + * locale + * @param icon path of application icon + */ + void setIconTargetFilenameForLocale(const std::string &icon); + + /** + * @brief getIconTargetFilename gets icon full path + * @param languageTag language tag + * @return value of full path + */ + std::string getInstalledIconPath() const; + + /** + * @brief getWidgetSourcePath return widget's source path given to installer + * @return value of source path + */ + std::string getWidgetSource() const; + /** + * @brief pkgid Returns pkgid + * @return pkgid + */ + DPL::String getPkgId() const; + + //external files + /** + * @brief registerExternalFile Registers file for database registration + * @param file + * + * Registered file will be stored in database and removed automatically a + * + * @return + */ + void registerExternalLocation(const std::string & file); + /** + * @brief listExternalFile list all file to be registered + */ + WrtDB::ExternalLocationList listExternalLocations() const; + + /* + * @brief set appid + */ + void registerAppid(const std::string & appid); +#ifdef SERVICE_ENABLED + void registerServiceAppid(const std::string & svcAppid); +#endif + + private: + std::string m_pkgid; //id of package + std::string m_widgetSource; // Source widget zip + // file/widget url + std::string m_appid; //id of app +#ifdef SERVICE_ENABLED + std::string m_svcAppid; +#endif + std::string m_iconPath; //installed icon path + WrtDB::PackagingType m_type; + std::shared_ptr m_temp; //directory + WrtDB::ExternalLocationList m_externals; + std::string m_installedPath; + InstallMode::ExtensionType m_extensionType; +}; + +#endif // WRT_INSTALLER_SRC_MISC_WIDGET_LOCATION_H diff --git a/src_wearable/pkg-manager/CMakeLists.txt b/src_wearable/pkg-manager/CMakeLists.txt new file mode 100755 index 0000000..d65c064 --- /dev/null +++ b/src_wearable/pkg-manager/CMakeLists.txt @@ -0,0 +1,77 @@ +# +# Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +SET(BACKLIB_SRCS + backendlib.cpp + ${PROJECT_SOURCE_DIR}/src/configuration_parser/widget_parser.cpp + ${PROJECT_SOURCE_DIR}/src/configuration_parser/parser_runner.cpp + ${PROJECT_SOURCE_DIR}/src/configuration_parser/ignoring_parser.cpp + ${PROJECT_SOURCE_DIR}/src/configuration_parser/deny_all_parser.cpp + ${PROJECT_SOURCE_DIR}/src/configuration_parser/libiriwrapper.cpp + ${PROJECT_SOURCE_DIR}/src/wrt-installer/language_subtag_rst_tree.cpp +) + +PKG_CHECK_MODULES(WRT_BACKLIB_PKGS + dpl-efl + dpl-wrt-dao-ro + dpl-wrt-dao-rw + dpl-utils-efl + pkgmgr-installer + pkgmgr-types + pkgmgr + dlog + libpcrecpp + wrt-commons-i18n-dao-ro + REQUIRED) + +INCLUDE_DIRECTORIES( + ${WRT_BACKLIB_PKGS_INCLUDE_DIRS} + ${PROJECT_SOURCE_DIR}/src/configuration_parser +) + +ADD_LIBRARY(${TARGET_BACKEND_LIB} SHARED + ${BACKLIB_SRCS} +) + +TARGET_LINK_LIBRARIES(${TARGET_BACKEND_LIB} + ${WRT_BACKLIB_PKGS_LIBRARIES} +) + +SET_TARGET_PROPERTIES(${TARGET_BACKEND_LIB} PROPERTIES + LINK_FLAGS "-Wl,--as-needed -Wl,--hash-style=both" +) + +INSTALL(TARGETS ${TARGET_BACKEND_LIB} + DESTINATION etc/package-manager/backendlib + PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE +) + +#SYMLINK +set(SYMLINK_USE OFF) +set(SYMLINK_DEST "${CMAKE_INSTALL_PREFIX}/etc/package-manager") + +IF(SYMLINK_USE) + ADD_CUSTOM_COMMAND(OUTPUT ${SYMLINK_DEST}/backend/wgt + COMMAND mkdir + ARGS -p ${SYMLINK_DEST}/backend + COMMAND ln + ARGS -sf ${CMAKE_INSTALL_PREFIX}/bin/${BACKEND} ${SYMLINK_DEST}/backend/wgt + DEPENDS ${BACKEND} + ) + ADD_CUSTOM_TARGET(test_symlinks ALL + DEPENDS ${SYMLINK_DEST}/backend/wgt + ) +ENDIF(SYMLINK_USE) diff --git a/src_wearable/pkg-manager/DESCRIPTION b/src_wearable/pkg-manager/DESCRIPTION new file mode 100644 index 0000000..a9d3696 --- /dev/null +++ b/src_wearable/pkg-manager/DESCRIPTION @@ -0,0 +1 @@ +Executables for interfacing with the package manager diff --git a/src_wearable/pkg-manager/backendlib.cpp b/src_wearable/pkg-manager/backendlib.cpp new file mode 100644 index 0000000..4260d1e --- /dev/null +++ b/src_wearable/pkg-manager/backendlib.cpp @@ -0,0 +1,570 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * + * + * @file backendlib.cpp + * @author Soyoung Kim (sy037.kim@samsung.com) + * @version 0.1 + * @brief This is implementation file for providing widget information + * to package manager + */ +#include "package-manager-plugin.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "root_parser.h" +#include "widget_parser.h" +#include "parser_runner.h" +#include + +using namespace WrtDB; + +#undef TRUE +#undef FALSE +#define TRUE 0 +#define FALSE -1 +#define GET_DIRECTORY_SIZE_KB(x) (x) / 1024 + +#ifdef __cplusplus +extern "C" +{ +#endif + +static void pkg_native_plugin_on_unload(); +static int pkg_plugin_app_is_installed(const char *pkg_name); +static int pkg_plugin_get_installed_apps_list(const char *category, + const char *option, + package_manager_pkg_info_t **list, + int *count); +static int pkg_plugin_get_app_detail_info( + const char *pkg_name, + package_manager_pkg_detail_info_t * + pkg_detail_info); +static int pkg_plugin_get_app_detail_info_from_package( + const char *pkg_path, + package_manager_pkg_detail_info_t + *pkg_detail_info); + +pkgmgr_info *pkgmgr_client_check_pkginfo_from_file(const char *pkg_path); + +static void pkg_native_plugin_on_unload() +{ + _D("pkg_native_plugin_unload() is called"); +} + +static int pkg_plugin_app_is_installed(const char *pkg_name) +{ + const char* REG_PKGID_PATTERN = "^[a-zA-Z0-9]{10}$"; + _D("pkg_plugin_app_is_installed() is called"); + + WrtDB::WrtDatabase::attachToThreadRO(); + + regex_t reg; + if (regcomp(®, REG_PKGID_PATTERN, REG_NOSUB | REG_EXTENDED) != 0) { + _D("Regcomp failed"); + } + + WrtDB::TizenAppId appid; + + if (!(regexec(®, pkg_name, + static_cast(0), NULL, 0) == 0)) + { + _E("Invalid argument : %s", pkg_name); + return FALSE; + } + + Try { + WrtDB::TizenPkgId pkgid(DPL::FromUTF8String(pkg_name)); + appid = WidgetDAOReadOnly::getTizenAppId(pkgid); + _D("appid : %ls", appid.c_str()); + } Catch(WidgetDAOReadOnly::Exception::WidgetNotExist) { + WrtDB::WrtDatabase::detachFromThread(); + return FALSE; + } + WrtDB::WrtDatabase::detachFromThread(); + return TRUE; +} + +static int pkg_plugin_get_installed_apps_list(const char * /*category*/, + const char * /*option*/, + package_manager_pkg_info_t **list, + int *count) +{ + _D("pkg_plugin_get_installed_apps_list() is called"); + + package_manager_pkg_info_t *pkg_list = NULL; + package_manager_pkg_info_t *pkg_last = NULL; + + WrtDB::WrtDatabase::attachToThreadRO(); + TizenAppIdList tizenAppIdList = WidgetDAOReadOnly::getTizenAppIdList(); + *count = 0; + + FOREACH(iterator, tizenAppIdList) { + package_manager_pkg_info_t *pkg_info = + static_cast + (malloc(sizeof(package_manager_pkg_info_t))); + + if (NULL == pkg_list) { + pkg_list = pkg_info; + pkg_last = pkg_info; + } else { + pkg_last->next = pkg_info; + } + + TizenAppId tzAppid = *iterator; + WidgetDAOReadOnly widget(tzAppid); + strncpy(pkg_info->pkg_type, "wgt", PKG_TYPE_STRING_LEN_MAX); + snprintf(pkg_info->pkg_name, PKG_NAME_STRING_LEN_MAX, "%s", + DPL::ToUTF8String(tzAppid).c_str()); + + DPL::OptionalString version = widget.getVersion(); + if (!!version) { + strncpy(pkg_info->version, + DPL::ToUTF8String(*version).c_str(), + PKG_VERSION_STRING_LEN_MAX - 1); + } + + (*count)++; + pkg_last = pkg_info; + } + *list = pkg_list; + WrtDB::WrtDatabase::detachFromThread(); + + return TRUE; +} + +static int pkg_plugin_get_app_detail_info( + const char *pkg_name, + package_manager_pkg_detail_info_t * + pkg_detail_info) +{ + _D("pkg_plugin_get_app_detail_info() is called"); + + WrtDB::WrtDatabase::attachToThreadRO(); + + WrtDB::TizenAppId appid; + Try { + WrtDB::TizenPkgId pkgid(DPL::FromUTF8String(pkg_name)); + appid = WidgetDAOReadOnly::getTizenAppId(pkgid); + _D("appid : %ls", appid.c_str()); + } Catch(WidgetDAOReadOnly::Exception::WidgetNotExist) { + WrtDB::WrtDatabase::detachFromThread(); + return FALSE; + } + + WidgetDAOReadOnly widget(appid); + + DPL::OptionalString version = widget.getVersion(); + DPL::OptionalString id = widget.getGUID(); + DPL::OptionalString locale = widget.getDefaultlocale(); + + if (!!version) { + strncpy(pkg_detail_info->version, + DPL::ToUTF8String(*version).c_str(), + PKG_VERSION_STRING_LEN_MAX - 1); + } + snprintf(pkg_detail_info->pkgid, PKG_NAME_STRING_LEN_MAX, "%s", + pkg_name); + snprintf(pkg_detail_info->optional_id, PKG_NAME_STRING_LEN_MAX, "%s", + DPL::ToUTF8String(appid).c_str()); + WidgetLocalizedInfo localizedInfo; + + if (!locale) { + _D("locale is NULL"); + DPL::String languageTag(L""); + localizedInfo = widget.getLocalizedInfo(languageTag); + } else { + localizedInfo = widget.getLocalizedInfo(*locale); + } + DPL::OptionalString desc(localizedInfo.description); + + if (!!desc) { + strncpy(pkg_detail_info->pkg_description, + DPL::ToUTF8String(*desc).c_str(), + PKG_VALUE_STRING_LEN_MAX - 1); + } + strncpy(pkg_detail_info->pkg_type, "wgt", PKG_TYPE_STRING_LEN_MAX); + strncpy(pkg_detail_info->pkg_name, pkg_name, PKG_NAME_STRING_LEN_MAX - 1); + + std::string min_version = DPL::ToUTF8String((*widget.getMinimumWacVersion())); + + strncpy(pkg_detail_info->min_platform_version, min_version.c_str(), + PKG_VERSION_STRING_LEN_MAX - 1); + + /* set installed time */ + pkg_detail_info->installed_time = widget.getInstallTime(); + + /* set Widget size */ + DPL::String pkgName = DPL::FromUTF8String(pkg_name); + std::string installPath = WidgetConfig::GetWidgetBasePath(pkgName); + std::string persistentPath = + WidgetConfig::GetWidgetPersistentStoragePath(pkgName); + std::string tempPath = + WidgetConfig::GetWidgetTemporaryStoragePath(pkgName); + installPath += "/"; + tempPath += "/"; + persistentPath += "/"; + + size_t installedSize = Utils::getFolderSize(installPath); + size_t persistentSize = Utils::getFolderSize(persistentPath); + size_t appSize = installedSize - persistentSize; + size_t dataSize = persistentSize + Utils::getFolderSize(tempPath); + + pkg_detail_info->installed_size = GET_DIRECTORY_SIZE_KB(installedSize); + pkg_detail_info->app_size = GET_DIRECTORY_SIZE_KB(appSize); + pkg_detail_info->data_size = GET_DIRECTORY_SIZE_KB(dataSize); + + WrtDB::WrtDatabase::detachFromThread(); + return TRUE; +} + +int getConfigParserData(const std::string &widgetPath, ConfigParserData& configInfo) +{ + const char* CONFIG_XML = "config.xml"; + const char* WITH_OSP_XML = "res/wgt/config.xml"; + + Try { + ParserRunner parser; + + std::unique_ptr zipFile( + new DPL::ZipInput(widgetPath)); + + std::unique_ptr configFile; + + // Open config.xml file + Try { + configFile.reset(zipFile->OpenFile(CONFIG_XML)); + } + Catch(DPL::ZipInput::Exception::OpenFileFailed) + { + configFile.reset(zipFile->OpenFile(WITH_OSP_XML)); + } + + // Extract config + DPL::BinaryQueue buffer; + DPL::AbstractWaitableInputAdapter inputAdapter(configFile.get()); + DPL::AbstractWaitableOutputAdapter outputAdapter(&buffer); + DPL::Copy(&inputAdapter, &outputAdapter); + parser.Parse(&buffer, + ElementParserPtr( + new RootParser(configInfo, + DPL:: + FromUTF32String( + L"widget")))); + } + Catch(DPL::ZipInput::Exception::OpenFailed) + { + _E("Failed to open widget package"); + return FALSE; + } + Catch(DPL::ZipInput::Exception::OpenFileFailed) + { + _E("Failed to open config.xml file"); + return FALSE; + } + Catch(DPL::CopyFailed) + { + _E("Failed to extract config.xml file"); + return FALSE; + } + Catch(DPL::FileInput::Exception::OpenFailed) + { + _E("Failed to open config.xml file"); + return FALSE; + } + Catch(ElementParser::Exception::ParseError) + { + _E("Failed to parse config.xml file"); + return FALSE; + } + Catch(DPL::ZipInput::Exception::SeekFileFailed) + { + _E("Failed to seek widget archive - corrupted package?"); + return FALSE; + } + + return TRUE; +} + +char* getIconInfo(const std::string &widgetPath, + const std::string &icon_name, int &icon_size) +{ + Try { + std::unique_ptr zipFile( + new DPL::ZipInput(widgetPath)); + + std::unique_ptr iconFile; + + Try { + iconFile.reset(zipFile->OpenFile(icon_name)); + } + Catch(DPL::ZipInput::Exception::OpenFileFailed) + { + _D("This web app is hybrid web app"); + std::string hybrid_icon = "res/wgt/" + icon_name; + iconFile.reset(zipFile->OpenFile(hybrid_icon)); + } + + DPL::BinaryQueue buffer; + DPL::AbstractWaitableInputAdapter inputAdapter(iconFile.get()); + DPL::AbstractWaitableOutputAdapter outputAdapter(&buffer); + DPL::Copy(&inputAdapter, &outputAdapter); + icon_size = buffer.Size(); + char *getBuffer = (char*) calloc(1, (sizeof(char) * icon_size) + 1); + buffer.Flatten(getBuffer, buffer.Size()); + return getBuffer; + } + Catch(DPL::ZipInput::Exception::OpenFailed) + { + _D("Failed to open widget package"); + return NULL; + } + Catch(DPL::ZipInput::Exception::OpenFileFailed) + { + _D("Not found icon file %s", icon_name.c_str()); + return NULL; + } +} + +char* getIconForLocale(const std::string& bp, const std::string& tag, + const std::string& icon, int & size) +{ + std::string iconPath; + if (!tag.empty()) { + iconPath += std::string("locales/") + tag; + } + if (!iconPath.empty()) { + iconPath += "/"; + } + + iconPath += icon; + return getIconInfo(bp, iconPath, size); +} + +char* getIcon(const std::string & basepath, const WrtDB::ConfigParserData & config, int & size) +{ + const std::list defaultIcons{ "icon.svg", "icon.ico", "icon.png", "icon.gif", "icon.jpg" }; + LanguageTags tagsList = + LanguageTagsProviderSingleton::Instance().getLanguageTags(); + + char * result = NULL; + + //for each locale tag - searching for icon presence and returning raw data + //first found is best as locale tags are ordered + FOREACH(tag, tagsList) + { + FOREACH(icon, config.iconsList) + { + std::string src = DPL::ToUTF8String(icon->src); + result = getIconForLocale(basepath, DPL::ToUTF8String(*tag), src, size); + if(result) { + return result; + } + } + FOREACH(i, defaultIcons) + { + result = getIconForLocale(basepath, DPL::ToUTF8String(*tag), *i, size); + if(result) { + return result; + } + } + } + return NULL; +} + +int getWidgetDetailInfoFromPackage(const char* pkgPath, + package_manager_pkg_detail_info_t* pkg_detail_info) +{ + const std::string widget_path(pkgPath); + ConfigParserData configInfo; + + if (FALSE == getConfigParserData(widget_path, configInfo)) { + return FALSE; + } + + strncpy(pkg_detail_info->pkg_type, "wgt", PKG_TYPE_STRING_LEN_MAX); + if (!!configInfo.tizenPkgId) { + strncpy(pkg_detail_info->pkgid, + DPL::ToUTF8String(*configInfo.tizenPkgId).c_str(), PKG_TYPE_STRING_LEN_MAX - 1); + } + if (!!configInfo.tizenAppId) { + strncpy(pkg_detail_info->pkg_name, + DPL::ToUTF8String(*configInfo.tizenAppId).c_str(), + PKG_NAME_STRING_LEN_MAX - 1); + } + if (!!configInfo.version) { + strncpy(pkg_detail_info->version, + DPL::ToUTF8String(*configInfo.version).c_str(), + PKG_VERSION_STRING_LEN_MAX - 1); + } + + DPL::OptionalString name; + DPL::OptionalString desc; + + LanguageTags tags = LanguageTagsProviderSingleton::Instance().getLanguageTags(); + + auto toLowerCase = [](const DPL::String & r) + { + DPL::String result; + std::transform(r.begin(), r.end(), std::inserter(result, result.begin()), ::tolower); + return result; + }; + + if (!!configInfo.defaultlocale) + { + Locale & dl = *configInfo.defaultlocale; + configInfo.defaultlocale = toLowerCase(dl); + } + + bool found = false; + FOREACH(tag, tags) + { + *tag = toLowerCase(*tag); + FOREACH(localizedData, configInfo.localizedDataSet) + { + Locale i = localizedData->first; + i = toLowerCase(i); + + if (!!configInfo.defaultlocale && *configInfo.defaultlocale == i) + { + name = localizedData->second.name; + desc = localizedData->second.description; + } + if (*tag == i) + { + name = localizedData->second.name; + desc = localizedData->second.description; + found = true; + break; + } + } + if(found) break; + } + + if (!!name) { + strncpy(pkg_detail_info->label, DPL::ToUTF8String(*name).c_str(), + PKG_LABEL_STRING_LEN_MAX - 1); + } + + if (!!desc) { + strncpy(pkg_detail_info->pkg_description, + DPL::ToUTF8String(*desc).c_str(), + PKG_VALUE_STRING_LEN_MAX - 1); + } + + if (!!configInfo.tizenMinVersionRequired) { + strncpy(pkg_detail_info->min_platform_version, + DPL::ToUTF8String(*configInfo.tizenMinVersionRequired).c_str(), + PKG_VERSION_STRING_LEN_MAX - 1); + } + + if (!!configInfo.authorName) { + strncpy(pkg_detail_info->author, + DPL::ToUTF8String(*configInfo.authorName).c_str(), + PKG_VALUE_STRING_LEN_MAX - 1); + } + + + pkg_detail_info->privilege_list = NULL; + FOREACH(it, configInfo.featuresList) { + std::string featureInfo = DPL::ToUTF8String(it->name); + _D("privilege : %s", featureInfo.c_str()); + int length = featureInfo.size(); + char *privilege = (char*) calloc(1, (sizeof(char) * (length + 1))); + snprintf(privilege, length + 1, "%s", featureInfo.c_str()); + pkg_detail_info->privilege_list = + g_list_append(pkg_detail_info->privilege_list, privilege); + } + + char* icon_buf = getIcon(widget_path, configInfo, pkg_detail_info->icon_size); + + if (icon_buf) { + _D("icon size : %d", pkg_detail_info->icon_size); + pkg_detail_info->icon_buf = icon_buf; + } else { + _D("No icon"); + pkg_detail_info->icon_size = 0; + pkg_detail_info->icon_buf = NULL; + } + + return TRUE; +} + +static int pkg_plugin_get_app_detail_info_from_package( + const char * pkg_path, + package_manager_pkg_detail_info_t * pkg_detail_info) +{ + _D("pkg_plugin_get_app_detail_info_from_package() is called"); + return getWidgetDetailInfoFromPackage(pkg_path, pkg_detail_info); +} + +pkgmgr_info *pkgmgr_client_check_pkginfo_from_file(const char *pkg_path) +{ + _D("pkgmgr_client_check_pkginfo_from_file() is called"); + package_manager_pkg_detail_info_t *pkg_detail_info; + pkg_detail_info = (package_manager_pkg_detail_info_t*)malloc( + sizeof(package_manager_pkg_detail_info_t)); + int ret = getWidgetDetailInfoFromPackage(pkg_path, pkg_detail_info); + if (FALSE == ret) { + _E("Failed to get package detail info "); + free(pkg_detail_info); + return NULL; + } + return reinterpret_cast(pkg_detail_info); +} + +__attribute__ ((visibility("default"))) +int pkg_plugin_on_load(pkg_plugin_set *set) +{ + DPL::Log::LogSystemSingleton::Instance().SetTag("WGT-BACKLIB"); + if (NULL == set) { + return FALSE; + } + memset(set, 0x00, sizeof(pkg_plugin_set)); + + set->plugin_on_unload = pkg_native_plugin_on_unload; + set->pkg_is_installed = pkg_plugin_app_is_installed; + set->get_installed_pkg_list = pkg_plugin_get_installed_apps_list; + set->get_pkg_detail_info = pkg_plugin_get_app_detail_info; + set->get_pkg_detail_info_from_package = + pkg_plugin_get_app_detail_info_from_package; + + return TRUE; +} + +#ifdef __cplusplus +} +#endif diff --git a/src_wearable/pkg-manager/pkgmgr_signal.cpp b/src_wearable/pkg-manager/pkgmgr_signal.cpp new file mode 100644 index 0000000..a5f2383 --- /dev/null +++ b/src_wearable/pkg-manager/pkgmgr_signal.cpp @@ -0,0 +1,297 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @author Yunchan Cho (yunchan.cho@samsung.com) + * @version 0.1 + * @brief + */ + +#include +#include + +#include +#include +#include + +namespace { +// package type sent in every signal +const char PKGMGR_WEBAPP_TYPE[] = "wgt"; + +// notification about opoeration start +const char PKGMGR_START_KEY[] = "start"; + +// value for new installation +const char PKGMGR_START_INSTALL[] = "install"; + +// value for update installation +const char PKGMGR_START_UPDATE[] = "update"; + +// value for uninstallation +const char PKGMGR_START_UNINSTALL[] = "uninstall"; + +// notification about progress of installation with percentage number +const char PKGMGR_PROGRESS_KEY[] = "install_percent"; + +// notification about icon path for installation frontend +const char PKGMGR_ICON_PATH[] = "icon_path"; + +// notification about error before end with given error code +// (currently, same as backend exit status) +const char PKGMGR_ERROR[] = "error"; + +// notification about end of installation with status +const char PKGMGR_END_KEY[] = "end"; + +// success value of end of installation +const char PKGMGR_END_SUCCESS[] = "ok"; + +// failure value of end of installation +const char PKGMGR_END_FAILURE[] = "fail"; +} + +namespace PackageManager { +PkgmgrSignal::PkgmgrSignal() : + m_initialized(false), + m_handle(NULL), + m_reqType(RequestType::UNSUPPORTED), + m_percent(0) +{} + +PkgmgrSignal::~PkgmgrSignal() +{ + deinitialize(); +} + +bool PkgmgrSignal::initialize(int argc, char* argv[]) +{ + if (m_handle) { + _D("Release already allocated pkgmgr handle"); + pkgmgr_installer_free(m_handle); + m_handle = NULL; + } + + m_handle = pkgmgr_installer_new(); + if (!m_handle) { + _E("Fail to get pkgmgr installer handle"); + return false; + } + + // set information from pkgmgr + if (!pkgmgr_installer_receive_request( + m_handle, argc, argv)) + { + auto pkgmgrtype = pkgmgr_installer_get_request_type(m_handle); + switch(pkgmgrtype) + { + case PKGMGR_REQ_INSTALL: + m_reqType = RequestType::INSTALL; + break; + case PKGMGR_REQ_UNINSTALL: + m_reqType = RequestType::UNINSTALL; + break; + case PKGMGR_REQ_REINSTALL: + m_reqType = RequestType::REINSTALL; + break; + default: + m_reqType = RequestType::UNSUPPORTED; + break; + } + + if (m_reqType == RequestType::UNSUPPORTED) + { + _E("Fail to get request type of pkgmgr"); + pkgmgr_installer_free(m_handle); + m_handle = NULL; + return false; + } + const char *callerId = pkgmgr_installer_get_caller_pkgid(m_handle); + if(callerId) + m_callerId = callerId; + + } else { + _E("Fail to get information of pkgmgr's request"); + pkgmgr_installer_free(m_handle); + m_handle = NULL; + return false; + } + + m_type = PKGMGR_WEBAPP_TYPE; + m_initialized = true; + return true; +} + +bool PkgmgrSignal::deinitialize() +{ + if (!m_initialized) { + _E("PkgmgrSingal not yet intialized"); + return false; + } + + if (!m_recoveryFile.empty() && (0 != unlink(m_recoveryFile.c_str()))) { + _E("Failed to remove %s", m_recoveryFile.c_str()); + } + + if (m_handle) { + pkgmgr_installer_free(m_handle); + } + + m_handle = NULL; + m_initialized = false; + return true; +} + +bool PkgmgrSignal::setPkgname(const std::string& name) +{ + if (!m_initialized) { + _E("PkgmgrSingal not yet intialized"); + return false; + } + + if (name.empty()) { + _E("name is empty"); + return false; + } + + m_pkgname = name; + _D("Success to set tizen package name: %s", m_pkgname.c_str()); + setRecoveryFile(); + + return true; +} + +void PkgmgrSignal::setRecoveryFile() +{ + std::string filePath = WrtDB::GlobalConfig::GetTempInstallInfoPath(); + filePath += "/" + m_pkgname; + + m_recoveryFile = filePath; + _D("SetRecoveryFile... %s", filePath.c_str()); + if (access(filePath.c_str(), F_OK) != 0) { + FILE *file = fopen(filePath.c_str(), "w"); + if (file != NULL) { + fclose(file); + } + } else { + _D("Recovery File : %s is already exist", filePath.c_str()); + } +} + +bool PkgmgrSignal::startJob(Jobs::InstallationType type) +{ + switch(type) + { + case Jobs::InstallationType::NewInstallation: + sendSignal(PKGMGR_START_KEY, PKGMGR_START_INSTALL); + break; + case Jobs::InstallationType::UpdateInstallation: + sendSignal(PKGMGR_START_KEY, PKGMGR_START_UPDATE); + break; + case Jobs::InstallationType::Uninstallation: + sendSignal(PKGMGR_START_KEY, PKGMGR_START_UNINSTALL); + break; + default: + _E("Trying to send unknown installation type to pkgmgr"); + return false; + } + return true; +} + +bool PkgmgrSignal::endJob(Jobs::Exceptions::Type ecode) +{ + if(ecode == Jobs::Exceptions::Type::Success) + { + return sendSignal(PKGMGR_END_KEY, PKGMGR_END_SUCCESS); + } + else + { + sendSignal(PKGMGR_ERROR, DPL::lexical_cast(ecode)); + return sendSignal(PKGMGR_END_KEY, PKGMGR_END_FAILURE); + } +} + +bool PkgmgrSignal::sendProgress(int percent) +{ + if (m_percent == percent) { + return true; + } + + m_percent = percent; + return sendSignal(PKGMGR_PROGRESS_KEY, DPL::lexical_cast(percent)); +} + +bool PkgmgrSignal::sendIconPath(const std::string & iconpath) +{ + return sendSignal(PKGMGR_ICON_PATH, iconpath); +} + +bool PkgmgrSignal::sendSignal(const std::string& key, + const std::string& value) const +{ + if (!m_initialized) { + _E("PkgmgrSingal not yet intialized"); + return false; + } + + if (key.empty() || value.empty()) { + _D("key or value is empty"); + return false; + } + + if (m_handle == NULL || m_type.empty()) { + _E("Some data of PkgmgrSignal is empty"); + return false; + } + + // send pkgmgr signal + if (pkgmgr_installer_send_signal( + m_handle, m_type.c_str(), m_pkgname.c_str(), + key.c_str(), value.c_str())) + { + _E("Fail to send pkgmgr signal"); + return false; + } + + _D("Success to send pkgmgr signal: %s - %s", key.c_str(), value.c_str()); + return true; +} + +std::string PkgmgrSignal::getPkgname() const +{ + if (!m_initialized) { + _E("PkgmgrSingal not yet intialized"); + } + + return m_pkgname; +} + +PkgmgrSignal::RequestType PkgmgrSignal::getRequestedType() const +{ + if (!m_initialized) { + _E("PkgmgrSingal not yet intialized"); + } + + return m_reqType; +} + +std::string PkgmgrSignal::getCallerId() const +{ + if (!m_initialized) { + _E("PkgmgrSingal not yet intialized"); + } + + return m_callerId; +} +} // PackageManager diff --git a/src_wearable/pkg-manager/pkgmgr_signal.h b/src_wearable/pkg-manager/pkgmgr_signal.h new file mode 100644 index 0000000..26ce559 --- /dev/null +++ b/src_wearable/pkg-manager/pkgmgr_signal.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @author Yunchan Cho (yunchan.cho@samsung.com) + * @author Jan Olszak (j.olszak@samsung.com) + * @version 0.2 + * @brief + */ + +#ifndef WRT_PKGMGR_SIGNAL_H_ +#define WRT_PKGMGR_SIGNAL_H_ + +#include + +struct pkgmgr_installer; + +namespace PackageManager { + +class PkgmgrSignal : public IPkgmgrSignal +{ +public: + enum class RequestType + { + UNSUPPORTED, + INSTALL, + UNINSTALL, + REINSTALL + }; + + bool initialize(int argc, char* argv[]); + bool deinitialize(); + bool setPkgname(const std::string& name); + std::string getPkgname() const; + RequestType getRequestedType() const; + std::string getCallerId() const; + + bool startJob(Jobs::InstallationType type); + bool endJob(Jobs::Exceptions::Type ecode); + bool sendProgress(int percent); + bool sendIconPath(const std::string & iconpath); + void setRecoveryFile(); + + PkgmgrSignal(); + virtual ~PkgmgrSignal(); + +protected: + bool sendSignal(const std::string& key, const std::string& value) const; + +private: + bool m_initialized; + pkgmgr_installer* m_handle; + std::string m_type; + std::string m_pkgname; + RequestType m_reqType; + std::string m_callerId; + int m_percent; + std::string m_recoveryFile; +}; +} // PackageManager + +#endif // WRT_PKGMGR_SIGNAL_H_ + diff --git a/src_wearable/pkg-manager/pkgmgr_signal_dummy.h b/src_wearable/pkg-manager/pkgmgr_signal_dummy.h new file mode 100644 index 0000000..42b0aa4 --- /dev/null +++ b/src_wearable/pkg-manager/pkgmgr_signal_dummy.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @author Jan Olszak (j.olszak@samsung.com) + * @version 0.1 + * @brief Dummy version of PkgmgrSignal. + */ + +#ifndef WRT_PKGMGR_SIGNAL_DUMMY_H_ +#define WRT_PKGMGR_SIGNAL_DUMMY_H_ + +#include + +#include + +namespace PackageManager { +class PkgmgrSignalDummy : public IPkgmgrSignal +{ + public: + PkgmgrSignalDummy() + {} + + virtual ~PkgmgrSignalDummy() + {} + + bool setPkgname(const std::string& /*name*/) + { + return false; + } + + std::string getPkgname() const + { + return ""; + } + + std::string getCallerId() const + { + return ""; + } + + bool startJob(Jobs::InstallationType type DPL_UNUSED) + { + return false; + } + + bool endJob(Jobs::Exceptions::Type ecode DPL_UNUSED) + { + return false; + } + + bool sendProgress(int percent DPL_UNUSED) + { + return false; + } + + bool sendIconPath(const std::string & iconpath DPL_UNUSED) + { + return false; + } +}; +} // PkgmgrSignalDummy + +#endif // WRT_PKGMGR_SIGNAL_DUMMY_H_ diff --git a/src_wearable/pkg-manager/pkgmgr_signal_interface.h b/src_wearable/pkg-manager/pkgmgr_signal_interface.h new file mode 100644 index 0000000..1e38a17 --- /dev/null +++ b/src_wearable/pkg-manager/pkgmgr_signal_interface.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @author Jan Olszak (j.olszak@samsung.com) + * @version 0.1 + * @brief Interface for PkgmgrSignal. + */ + +#ifndef WRT_PKGMGR_SIGNAL_INTERFACE_H_ +#define WRT_PKGMGR_SIGNAL_INTERFACE_H_ + +#include + +#include +#include + +namespace PackageManager { +class IPkgmgrSignal +{ + public: + virtual bool setPkgname(const std::string& name) = 0; + virtual std::string getPkgname() const = 0; + virtual std::string getCallerId() const = 0; + + virtual bool startJob(Jobs::InstallationType type) = 0; + virtual bool endJob(Jobs::Exceptions::Type ecode) = 0; + virtual bool sendProgress(int percent) = 0; + virtual bool sendIconPath(const std::string & iconpath) = 0; + virtual ~IPkgmgrSignal(){} +}; +} // IPkgmgrSignal + +#endif // WRT_PKGMGR_SIGNAL_INTERFACE_H_ diff --git a/src_wearable/wrt-installer/CMakeLists.txt b/src_wearable/wrt-installer/CMakeLists.txt new file mode 100644 index 0000000..533bcfa --- /dev/null +++ b/src_wearable/wrt-installer/CMakeLists.txt @@ -0,0 +1,75 @@ +# Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# @file CMakeLists.txt +# @author Lukasz Wrzosek (l.wrzosek@samsung.com) +# @version 1.0 +# + +SET(WRT_INSTALLER_DIR + ${INSTALLER_SRC_DIR}/wrt-installer + ) + +SET(PKG_MANAGER_DIR + ${INSTALLER_SRC_DIR}/pkg-manager + ) + +SET(WRT_INSTALLER_SOURCES + ${WRT_INSTALLER_DIR}/wrt-installer.cpp + ${WRT_INSTALLER_DIR}/installer_callbacks_translate.cpp + ${WRT_INSTALLER_DIR}/plugin_utils.cpp + ${WRT_INSTALLER_DIR}/language_subtag_rst_tree.cpp + ${WRT_INSTALLER_DIR}/installer_main_thread.cpp + ${WRT_INSTALLER_DIR}/command_parser.cpp + ${PKG_MANAGER_DIR}/pkgmgr_signal.cpp +) + +PKG_CHECK_MODULES(WRT_INSTALLER_DEPS + pkgmgr-installer + libpcrecpp + pkgmgr-info + pkgmgr + security-install + wrt-commons-i18n-dao-ro + capi-system-power + REQUIRED) + +INCLUDE_DIRECTORIES( + ${PKG_MANAGER_DIR} + ${WRT_INSTALLER_DEP_INCLUDES} + ${WRT_INSTALLER_INCLUDES} + ${WRT_INSTALLER_DEPS_INCLUDE_DIRS} +) + +ADD_EXECUTABLE(${TARGET_INSTALLER} + ${TARGET_INSTALLER_STATIC_SRC} + ${WRT_INSTALLER_SOURCES} +) + +ADD_DEFINITIONS(${WRT_INSTALLER_DEPS_CFLAGS}) + +TARGET_LINK_LIBRARIES(${TARGET_INSTALLER} + ${TARGET_INSTALLER_STATIC} + ${WRT_INSTALLER_DEPS_LIBRARIES} +) + + +SET_TARGET_PROPERTIES(${TARGET_INSTALLER} PROPERTIES + LINK_FLAGS "-Wl,--as-needed -Wl,--hash-style=both" + BUILD_WITH_INSTALL_RPATH ON + INSTALL_RPATH_USE_LINK_PATH ON +) + +INSTALL(TARGETS ${TARGET_INSTALLER} DESTINATION bin) diff --git a/src_wearable/wrt-installer/command_parser.cpp b/src_wearable/wrt-installer/command_parser.cpp new file mode 100644 index 0000000..2459596 --- /dev/null +++ b/src_wearable/wrt-installer/command_parser.cpp @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file command_parser.cpp + * @author Soyoung Kim (sy037.kim@samsung.com) + * @brief Implementation file for OptionParser. + */ + +#include +#include +#include +#include "command_parser.h" + +namespace { +typedef std::pair DataPair; + +const char* const KEY_OP = "op"; +const char* const KEY_PATH = "path"; +const char* const KEY_REMOVABLE = "removable"; +} + +bool CommandParser::CscCommandParser(const std::string& arg, CscOption &option) +{ + using namespace Command; + // path=/opt/system/csc/Ozq2iEG15R-2.0.0-arm.wgt:op=install:removable=true + // parsing CSC configuration string + _D("CscCommandParser"); + if (arg.empty()) { + return false; + } + DataMap cmdMap = ArgumentsParser(arg); + + DataMap::iterator it; + it = cmdMap.find(KEY_OP); + if (it == cmdMap.end()) { + return false; + } + + if (it->second == VALUE_INSTALL) { + _D("operation = %s", it->second.c_str()); + option.operation = VALUE_INSTALL; + it = cmdMap.find(KEY_PATH); + if (it == cmdMap.end()) { + return false; + } + option.path = it->second; + _D("path = %s", option.path.c_str()); + + it = cmdMap.find(KEY_REMOVABLE); + if (it == cmdMap.end()) { + return false; + } + + option.removable = true; + if (0 == it->second.compare(VALUE_FALSE)) { + option.removable = false; + } + } else if (it->second == VALUE_UNINSTALL) { + _D("operation = %s", it->second.c_str()); + // uninstall command isn't confirmed yet + it = cmdMap.find(KEY_PATH); + if (it == cmdMap.end()) { + return false; + } + option.path = it->second; + _D("operation = uninstall"); + _D("path = %s", option.path.c_str()); + } else { + _E("Unknown operation : %s", it->second.c_str()); + _D("operation = %s", it->second.c_str()); + return false; + } + + return true; +} + +bool CommandParser::FotaCommandParser(const std::string& arg, FotaOption + &option) +{ + using namespace Command; + // path=pkgid:op=install + _D("FotaCommandParser"); + DataMap cmdMap = ArgumentsParser(arg); + + DataMap::iterator it; + it = cmdMap.find(KEY_OP); + if (it == cmdMap.end()) { + return false; + } + option.operation = it->second; + + it = cmdMap.find(KEY_PATH); + if (it == cmdMap.end()) { + return false; + } + + option.pkgId = it->second; + _D("Fota : package_id [%s], operaion [%s]", option.pkgId.c_str(), + option.operation.c_str()); + + return true; +} + +CommandParser::DataMap CommandParser::ArgumentsParser(const std::string& arg) +{ + DataMap result; + + if (arg.empty()) { + _D("Input argument is empty"); + return result; + } + + const char* ptr = strtok(const_cast(arg.c_str()),":"); + while (ptr != NULL) { + std::string string = ptr; + ptr = strtok (NULL, ":"); + size_t pos = string.find('='); + if (pos == std::string::npos) { + continue; + } + result.insert( + DataPair(string.substr(0, pos), + string.substr(pos+1))); + } + + return result; +} diff --git a/src_wearable/wrt-installer/command_parser.h b/src_wearable/wrt-installer/command_parser.h new file mode 100755 index 0000000..49527f9 --- /dev/null +++ b/src_wearable/wrt-installer/command_parser.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file command_parser.h + * @author Soyoung Kim (sy037.kim@samsung.com) + * @brief Header file for Command parser + */ + +#ifndef WRT_INSTALLER_SRC_WRT_INSTALLER_COMMAND_PARSER_H_ +#define WRT_INSTALLER_SRC_WRT_INSTALLER_COMMAND_PARSER_H_ + +#include +#include +#include + +namespace Command { +const char* const VALUE_INSTALL = "install"; +const char* const VALUE_UNINSTALL = "uninstall"; +const char* const VALUE_UPGRADE = "upgrade"; +const char* const VALUE_UPDATE = "update"; +const char* const VALUE_TRUE = "true"; +const char* const VALUE_FALSE = "false"; +} + +class CommandParser +{ + typedef std::map DataMap; + + public: + struct CscOption { + std::string path; + std::string operation; + bool removable; + }; + + struct FotaOption { + std::string pkgId; + std::string operation; + }; + + static bool CscCommandParser(const std::string& arg, CscOption &option); + static bool FotaCommandParser(const std::string& arg, FotaOption &option); + + private: + static DataMap ArgumentsParser(const std::string& arg); +}; + +#endif diff --git a/src_wearable/wrt-installer/installer_callbacks_translate.cpp b/src_wearable/wrt-installer/installer_callbacks_translate.cpp new file mode 100644 index 0000000..ca52dd6 --- /dev/null +++ b/src_wearable/wrt-installer/installer_callbacks_translate.cpp @@ -0,0 +1,262 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file api_callbacks_translate.h + * @author Pawel Sikorski (p.sikorski@samsung.com) + * @version 1.0 + * @brief Source file for api callbacks translate functions + */ + +#include +#include +#include + +namespace InstallerCallbacksTranslate { + +// callback for finished install +void installFinishedCallback(void *userParam, + std::string tizenId, + Jobs::Exceptions::Type status) +{ + Assert(userParam != NULL); + + StatusCallbackStruct *apiStr = + static_cast(userParam); + + if (apiStr->status_callback) { + // Translate error + WrtErrStatus errorStatus; + + switch (status) { + case Jobs::Exceptions::Success: + errorStatus = WRT_SUCCESS; + break; + + case Jobs::Exceptions::ErrorPackageNotFound: + errorStatus = WRT_INSTALLER_ERROR_PACKAGE_NOT_FOUND; + break; + + case Jobs::Exceptions::ErrorPackageInvalid: + errorStatus = WRT_INSTALLER_ERROR_PACKAGE_INVALID; + break; + + case Jobs::Exceptions::ErrorPackageLowerVersion: + errorStatus = WRT_INSTALLER_ERROR_PACKAGE_LOWER_VERSION; + break; + + case Jobs::Exceptions::ErrorPackageExecutableNotFound: + errorStatus = WRT_INSTALLER_ERROR_PACKAGE_EXCUTABLE_NOT_FOUND; + break; + + case Jobs::Exceptions::ErrorManifestNotFound: + errorStatus = WRT_INSTALLER_ERROR_MANIFEST_NOT_FOUND; + break; + + case Jobs::Exceptions::ErrorManifestInvalid: + errorStatus = WRT_INSTALLER_ERROR_MANIFEST_INVALID; + break; + + case Jobs::Exceptions::ErrorConfigNotFound: + errorStatus = WRT_INSTALLER_CONFIG_NOT_FOUND; + break; + + case Jobs::Exceptions::ErrorConfigInvalid: + errorStatus = WRT_INSTALLER_ERROR_CONFIG_INVALID; + break; + + case Jobs::Exceptions::ErrorSignatureNotFound: + errorStatus = WRT_INSTALLER_ERROR_SIGNATURE_NOT_FOUND; + break; + + case Jobs::Exceptions::ErrorSignatureInvalid: + errorStatus = WRT_INSTALLER_ERROR_SIGNATURE_INVALID; + break; + + case Jobs::Exceptions::ErrorSignatureVerificationFailed: + errorStatus = WRT_INSTALLER_ERROR_SIGNATURE_VERIFICATION_FAILED; + break; + + case Jobs::Exceptions::ErrorRootCertificateNotFound: + errorStatus = WRT_INSTALLER_ERROR_ROOT_CERTIFICATE_NOT_FOUND; + break; + + case Jobs::Exceptions::ErrorCertificationInvaid: + errorStatus = WRT_INSTALLER_ERROR_CERTIFICATION_INVAID; + break; + + case + Jobs::Exceptions::ErrorCertificateChainVerificationFailed: + errorStatus = + WRT_INSTALLER_ERROR_CERTIFICATE_CHAIN_VERIFICATION_FAILED; + break; + + case Jobs::Exceptions::ErrorCertificateExpired: + errorStatus = WRT_INSTALLER_ERROR_CERTIFICATE_EXPIRED; + break; + + case Jobs::Exceptions::ErrorInvalidPrivilege: + errorStatus = WRT_INSTALLER_ERROR_INVALID_PRIVILEGE; + break; + + case Jobs::Exceptions::ErrorPrivilegeLevelViolation: + errorStatus = WRT_INSTALLER_ERROR_PRIVILEGE_LEVEL_VIOLATION; + break; + + case Jobs::Exceptions::ErrorMenuIconNotFound: + errorStatus = WRT_INSTALLER_ERROR_MENU_ICON_NOT_FOUND; + break; + + case Jobs::Exceptions::ErrorFatalError: + errorStatus = WRT_INSTALLER_ERROR_FATAL_ERROR; + break; + + case Jobs::Exceptions::ErrorOutOfStorage: + errorStatus = WRT_INSTALLER_ERROR_OUT_OF_STORAGE; + break; + + case Jobs::Exceptions::ErrorOutOfMemory: + errorStatus = WRT_INSTALLER_ERROR_OUT_OF_MEMORY; + break; + + case Jobs::Exceptions::ErrorArgumentInvalid: + errorStatus = WRT_INSTALLER_ERROR_ARGUMENT_INVALID; + break; + + case Jobs::Exceptions::ErrorPackageAlreadyInstalled: + errorStatus = WRT_INSTALLER_ERROR_PACKAGE_ALREADY_INSTALLED; + break; + + case Jobs::Exceptions::ErrorAceCheckFailed: + errorStatus = WRT_INSTALLER_ERROR_ACE_CHECK_FAILED; + break; + + case Jobs::Exceptions::ErrorManifestCreateFailed: + errorStatus = WRT_INSTALLER_ERROR_MANIFEST_CREATE_FAILED; + break; + + case Jobs::Exceptions::ErrorEncryptionFailed: + errorStatus = WRT_INSTALLER_ERROR_ENCRYPTION_FAILED; + break; + + case Jobs::Exceptions::ErrorInstallOspServcie: + errorStatus = WRT_INSTALLER_ERROR_INSTALL_OSP_SERVCIE; + break; + + default: + errorStatus = WRT_INSTALLER_ERROR_UNKNOWN; + break; + } + + // Callback + apiStr->status_callback(tizenId, errorStatus, apiStr->userdata); + } else { + _D("installFinishedCallback: No callback"); + } +} + +// callback for finished install +void uninstallFinishedCallback(void *userParam, + std::string tizenId, + Jobs::Exceptions::Type status) +{ + Assert(userParam != NULL); + + StatusCallbackStruct *apiStr = + static_cast(userParam); + + if (apiStr->status_callback) { + // Translate error + WrtErrStatus errorStatus; + + switch (status) { + case Jobs::Exceptions::Success: + errorStatus = WRT_SUCCESS; + break; + + case Jobs::Exceptions::ErrorWidgetUninstallationFailed: + errorStatus = WRT_INSTALLER_ERROR_UNINSTALLATION_FAILED; + break; + + case Jobs::Exceptions::ErrorUnknown: + errorStatus = WRT_INSTALLER_ERROR_UNKNOWN; + break; + + default: + errorStatus = WRT_INSTALLER_ERROR_UNKNOWN; + break; + } + + // Callback + apiStr->status_callback(tizenId, errorStatus, apiStr->userdata); + } else { + _D("uninstallFinishedCallback: No callback"); + } +} + +void pluginInstallFinishedCallback(void *userParam, + Jobs::Exceptions::Type status) +{ + Assert(userParam); + + PluginStatusCallbackStruct *apiStr = + static_cast(userParam); + + if (apiStr->statusCallback) { + // Translate error + WrtErrStatus errorStatus; + + switch (status) { + case Jobs::Exceptions::Success: + errorStatus = WRT_SUCCESS; + break; + case Jobs::Exceptions::ErrorPluginInstallationFailed: + errorStatus = WRT_INSTALLER_ERROR_PLUGIN_INSTALLATION_FAILED; + break; + default: + errorStatus = WRT_INSTALLER_ERROR_UNKNOWN; + break; + } + + apiStr->statusCallback(errorStatus, apiStr->userdata); + } else { + _D("PluginInstallFinishedCallback: No callback"); + } + + delete apiStr; +} + +// callback for progress of install OR uninstall +void installProgressCallback(void *userParam, + ProgressPercent percent, + const ProgressDescription &description) +{ + Assert(userParam != NULL); + + StatusCallbackStruct *apiStr = + static_cast(userParam); + + if (apiStr->progress_callback) { + //CALLBACK EXEC + _D("Entered %2.0f%% %s", percent, description.c_str()); + apiStr->progress_callback(static_cast(percent), + description.c_str(), + apiStr->userdata); + } else { + _D("installProgressCallback: ignoring NULL callback pointer"); + } +} +} //namespace + diff --git a/src_wearable/wrt-installer/installer_callbacks_translate.h b/src_wearable/wrt-installer/installer_callbacks_translate.h new file mode 100644 index 0000000..f20ecc2 --- /dev/null +++ b/src_wearable/wrt-installer/installer_callbacks_translate.h @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file api_callbacks_translate.h + * @author Pawel Sikorski (p.sikorski@samsung.com) + * @version 1.0 + * @brief Header file for api callbacks translate functions + */ +#ifndef WRT_SRC_API_API_CALLBACKS_TRANSLATE_H_ +#define WRT_SRC_API_API_CALLBACKS_TRANSLATE_H_ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +typedef void (*WrtInstallerInitCallback)(WrtErrStatus status, + void *data); +typedef void (*WrtPluginInstallerStatusCallback)(WrtErrStatus status, + void *data); +typedef void (*WrtInstallerStatusCallback)(std::string tizenId, + WrtErrStatus status, + void *data); +typedef void (*WrtProgressCallback)(float percent, + const char *description, + void *data); + + +namespace InstallerCallbacksTranslate { +struct StatusCallbackStruct +{ + void* userdata; + WrtInstallerStatusCallback status_callback; + WrtProgressCallback progress_callback; + + StatusCallbackStruct(void* u, + WrtInstallerStatusCallback s, + WrtProgressCallback p) : + userdata(u), + status_callback(s), + progress_callback(p) + {} +}; + +struct PluginStatusCallbackStruct +{ + void* userdata; + WrtPluginInstallerStatusCallback statusCallback; + WrtProgressCallback progressCallback; + + PluginStatusCallbackStruct(void* u, + WrtPluginInstallerStatusCallback s, + WrtProgressCallback p) : + userdata(u), + statusCallback(s), + progressCallback(p) + {} +}; + +void installFinishedCallback(void *userParam, + std::string tizenId, + Jobs::Exceptions::Type status); + +void uninstallFinishedCallback(void *userParam, + std::string tizenId, + Jobs::Exceptions::Type status); + +void pluginInstallFinishedCallback(void *userParam, + Jobs::Exceptions::Type status); + +// callback for progress of install OR uninstall +void installProgressCallback(void *userParam, + ProgressPercent percent, + const ProgressDescription &description); +} //namespace + +#endif /* WRT_SRC_API_API_CALLBACKS_TRANSLATE_H_ */ diff --git a/src_wearable/wrt-installer/installer_main_thread.cpp b/src_wearable/wrt-installer/installer_main_thread.cpp new file mode 100644 index 0000000..b398d3c --- /dev/null +++ b/src_wearable/wrt-installer/installer_main_thread.cpp @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file installer_main_thread.cpp + * @author Krzysztof Jackiewicz (k.jackiewicz@samsung.com) + * @version 1.0 + */ + +#include "installer_main_thread.h" +#include +#include +#include +#include +#include +#include +#include + +IMPLEMENT_SINGLETON(InstallerMainThread) + +using namespace WrtDB; + +InstallerMainThread::InstallerMainThread() : m_attached(false) {} + +InstallerMainThread::~InstallerMainThread() +{ + Assert(!m_attached); +} + +void InstallerMainThread::AttachDatabases() +{ + Assert(!m_attached); + // Attach databases + ValidationCore::AttachToThreadRW(); + ace_return_t ret = ace_install_initialize(); + Assert(ACE_OK == ret); // to be changed to exception in the future + WrtDB::WrtDatabase::attachToThreadRW(); + m_attached = true; +} + +void InstallerMainThread::DetachDatabases() +{ + Assert(m_attached); + m_attached = false; + // Detach databases + ValidationCore::DetachFromThread(); + ace_return_t ret = ace_install_shutdown(); + Assert(ACE_OK == ret); // to be changed to exception in the future + WrtDB::WrtDatabase::detachFromThread(); +} + +void InstallerMainThread::TouchArchitecture() +{ + // Touch controller + Logic::InstallerControllerSingleton::Instance().Touch(); +} + +void InstallerMainThread::TouchArchitectureOnlyInstaller() +{ + // Touch controller + Logic::InstallerControllerSingleton::Instance().Touch(); +} diff --git a/src_wearable/wrt-installer/installer_main_thread.h b/src_wearable/wrt-installer/installer_main_thread.h new file mode 100644 index 0000000..bd70b16 --- /dev/null +++ b/src_wearable/wrt-installer/installer_main_thread.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file installer_main_thread.h + * @author Krzysztof Jackiewicz (k.jackiewicz@samsung.com) + * @version 1.0 + */ + +#ifndef INSTALLER_MAINTHREAD_H_ +#define INSTALLER_MAINTHREAD_H_ + +#include + +class InstallerMainThread +{ + public: + void AttachDatabases(); + void DetachDatabases(); + void TouchArchitecture(); + void TouchArchitectureOnlyInstaller(); + + private: + friend class DPL::Singleton; + + InstallerMainThread(); + virtual ~InstallerMainThread(); + + bool m_attached; +}; + +typedef DPL::Singleton InstallerMainThreadSingleton; + +#endif /* INSTALLER_MAINTHREAD_H_ */ diff --git a/src_wearable/wrt-installer/language_subtag_rst_tree.cpp b/src_wearable/wrt-installer/language_subtag_rst_tree.cpp new file mode 100644 index 0000000..a2bfaf5 --- /dev/null +++ b/src_wearable/wrt-installer/language_subtag_rst_tree.cpp @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file language_subtag_rst_tree.cpp + * @author Lukasz Wrzosek (l.wrzosek@samsung.com) + * @version 1.0 + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +IMPLEMENT_SINGLETON(LanguageSubtagRstTree) + +namespace I18nDAOReadOnly = I18n::DB::I18nDAOReadOnly; + +bool LanguageSubtagRstTree::ValidateLanguageTag(const std::string &tag_input) +{ + std::string tag = tag_input; + std::transform(tag.begin(), tag.end(), tag.begin(), &tolower); + + std::vector parts; + DPL::Tokenize(DPL::FromUTF8String(tag), + '-', + std::back_inserter(parts), + false); + std::vector::iterator token = parts.begin(); + if (token == parts.end()) + { + return false; + } + + I18n::DB::Interface::attachDatabaseRO(); + DPL_SCOPE_EXIT() + { + I18n::DB::Interface::detachDatabase(); + }; + + if (I18nDAOReadOnly::IsValidSubTag(*token, RECORD_TYPE_LANGUAGE)) + { + ++token; + } + else + { + return false; + } + + if (token == parts.end()) + { + return true; + } + + if (I18nDAOReadOnly::IsValidSubTag(*token, RECORD_TYPE_EXTLANG)) + { + ++token; + } + + if (token == parts.end()) + { + return true; + } + + if (I18nDAOReadOnly::IsValidSubTag(*token, RECORD_TYPE_SCRIPT)) + { + ++token; + } + + if (token == parts.end()) + { + return true; + } + + if (I18nDAOReadOnly::IsValidSubTag(*token, RECORD_TYPE_REGION)) + { + ++token; + } + + if (token == parts.end()) + { + return true; + } + + while (token != parts.end()) + { + if (I18nDAOReadOnly::IsValidSubTag(*token, RECORD_TYPE_VARIANT)) + { + ++token; + } + else + { + break; + } + } + + //'u' - unicode extension - only one BCP47 extension is registered. + //TODO: unicode extension should be also validated (l.wrzosek) + if (token == parts.end()) + { + return true; + } + + if (*token == L"u") + { + ++token; + bool one_or_more = false; + while (token != parts.end() && + token->size() > 1 && + token->size() <= 8) + { + one_or_more = true; + ++token; + } + if (!one_or_more) + { + return false; + } + } + + //'x' - privateuse + if (token == parts.end()) + { + return true; + } + + if (*token == L"x") + { + ++token; + bool one_or_more = false; + while (token != parts.end() && + !token->empty() && + token->size() <= 8) + { + one_or_more = true; + ++token; + } + if (!one_or_more) + { + return false; + } + } + + if (token == parts.end()) + { + return true; + } + + //Try private use now: + token = parts.begin(); + if (*token == L"x") + { + ++token; + bool one_or_more = false; + while (token != parts.end() && + !token->empty() && + token->size() <= 8) + { + one_or_more = true; + ++token; + } + return one_or_more; + } + + //grandfathered is always rejected + return false; +} + +#define TEST_LANG(str, cond) \ + if (LanguageSubtagRstTreeSingleton::Instance(). \ + ValidateLanguageTag(str) == cond) { \ + _D("Good validate status for lang: %s", str); \ + } else { \ + _E("Wrong validate status for lang: %s, should be %d", str, cond); \ + } + +void LanguageSubtagRstTree::Initialize() +{ + /* Temporarily added unit test. Commented out due to performance drop. + * TEST_LANG("zh", true); + * TEST_LANG("esx-al", true); + * TEST_LANG("zh-Hant", true); + * TEST_LANG("zh-Hant-CN", true); + * TEST_LANG("zh-Hant-CN-x-private1-private2", true); + * TEST_LANG("plxxx", false); + * TEST_LANG("pl-x-private111", false); + * TEST_LANG("x-private1", false); //do not support pure private ones + * TEST_LANG("x-private22", false); + * TEST_LANG("i-private22", false); //do not support i-* + */ +} + +#undef TEST_LANG diff --git a/src_wearable/wrt-installer/language_subtag_rst_tree.h b/src_wearable/wrt-installer/language_subtag_rst_tree.h new file mode 100644 index 0000000..b057059 --- /dev/null +++ b/src_wearable/wrt-installer/language_subtag_rst_tree.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file language_subtag_rst_tree.h + * @author Lukasz Wrzosek (l.wrzosek@samsung.com) + * @version 1.0 + */ +#ifndef LANGUAGE_SUBTAG_RST_TREE_H +#define LANGUAGE_SUBTAG_RST_TREE_H + +#include +#include +#include +class LanguageSubtagRstTree : DPL::Noncopyable +{ + public: + void Initialize(); + bool ValidateLanguageTag(const std::string &tag); +}; + +typedef DPL::Singleton LanguageSubtagRstTreeSingleton; + +enum iana_record_types_e +{ + RECORD_TYPE_LANGUAGE, + RECORD_TYPE_SCRIPT, + RECORD_TYPE_REGION, + RECORD_TYPE_VARIANT, + RECORD_TYPE_GRANDFATHERED, + RECORD_TYPE_REDUNDANT, + RECORD_TYPE_EXTLANG +}; + +#endif //LANGUAGE_SUBTAG_RST_TREE_H diff --git a/src_wearable/wrt-installer/plugin_utils.cpp b/src_wearable/wrt-installer/plugin_utils.cpp new file mode 100644 index 0000000..cabda19 --- /dev/null +++ b/src_wearable/wrt-installer/plugin_utils.cpp @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file plugin-utils.cpp + * @author + * @version 1.0 + * @brief Header file for plugin util + */ + +#include +#include "plugin_utils.h" +#include +#include +#include +#include + +using namespace WrtDB; + +namespace PluginUtils { +const char* PLUGIN_INSTALL_LOCK_FILE = "/tmp/.wrt_plugin_install_lock"; + +static int s_plugin_install_lock_fd = -1; + +bool lockPluginInstallation(bool isPreload) +{ + if (isPreload) { + fprintf(stderr, "Skip create lock file.. \n"); + return true; + } + + int ret = 0; + + _D("Try to lock for plugins installation."); + + s_plugin_install_lock_fd = + open(PLUGIN_INSTALL_LOCK_FILE, O_RDONLY | O_CREAT, 0666); + + if (s_plugin_install_lock_fd == -1) { + _E("Lock file open failed!"); + + return false; + } + + ret = flock(s_plugin_install_lock_fd, LOCK_EX); //lock with waiting + + if (ret == -1) { + _E("Lock failed!"); + + close(s_plugin_install_lock_fd); + s_plugin_install_lock_fd = -1; + + return false; + } + + return true; +} + +bool unlockPluginInstallation(bool isPreload) +{ + _D("Unlock for plugins installation."); + if (isPreload) { + fprintf(stderr, "Skip plugin unlock.. \n"); + return true; + } + + if (s_plugin_install_lock_fd != -1) { + int ret = 0; + + ret = flock(s_plugin_install_lock_fd, LOCK_UN); //unlock + + if (ret == -1) { + _E("Unlock failed!"); + } + + close(s_plugin_install_lock_fd); + s_plugin_install_lock_fd = -1; + + return true; + } else { + _E("Lock file was not created!"); + } + + return false; +} + +bool checkPluginInstallationRequired() +{ + std::string installRequest = + std::string(GlobalConfig::GetPluginInstallInitializerName()); + + FileState::Type installationRequest = + checkFile(installRequest); + + switch (installationRequest) { + case FileState::FILE_EXISTS: + return true; + case FileState::FILE_NOT_EXISTS: + return false; + default: + _W("Opening installation request file failed"); + return false; + } +} + +bool removeInstallationRequiredFlag() +{ + std::string installRequest = + std::string(GlobalConfig::GetPluginInstallInitializerName()); + + return removeFile(installRequest); +} + +//checks if file exists and is regular file +FileState::Type checkFile(const std::string& filename) +{ + struct stat tmp; + + if (-1 == stat(filename.c_str(), &tmp)) { + if (ENOENT == errno) { + return FileState::FILE_NOT_EXISTS; + } + return FileState::FILE_READ_DATA_ERROR; + } else if (!S_ISREG(tmp.st_mode)) { + return FileState::FILE_EXISTS_NOT_REGULAR; + } + return FileState::FILE_EXISTS; +} + +bool removeFile(const std::string& filename) +{ + if (0 != unlink(filename.c_str())) { + return false; + } + + return true; +} +} //namespace PluginUtils diff --git a/src_wearable/wrt-installer/plugin_utils.h b/src_wearable/wrt-installer/plugin_utils.h new file mode 100644 index 0000000..8659f20 --- /dev/null +++ b/src_wearable/wrt-installer/plugin_utils.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file plugin-utils.h + * @author + * @version 1.0 + * @brief Header file for plugin util + */ +#ifndef PLUGIN_UTILS_H +#define PLUGIN_UTILS_H + +#include +#include + +namespace PluginUtils { +struct FileState +{ + enum Type + { + FILE_EXISTS, + FILE_EXISTS_NOT_REGULAR, + FILE_NOT_EXISTS, + FILE_READ_DATA_ERROR + }; +}; + +bool lockPluginInstallation(bool isPreload); +bool unlockPluginInstallation(bool isPreload); +bool checkPluginInstallationRequired(); +bool removeInstallationRequiredFlag(); +FileState::Type checkFile(const std::string& filename); +bool removeFile(const std::string& filename); +} +#endif // PLUGIN_UTILS_H diff --git a/src_wearable/wrt-installer/wrt-installer.cpp b/src_wearable/wrt-installer/wrt-installer.cpp new file mode 100755 index 0000000..9fc4df6 --- /dev/null +++ b/src_wearable/wrt-installer/wrt-installer.cpp @@ -0,0 +1,1497 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* @file wrt-installer.cpp + * @version 1.0 + * @brief Implementation file for installer + */ + +#include "wrt-installer.h" +#include "plugin_utils.h" + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace WrtDB; + +namespace { // anonymous +const char * const PKGMGR_INSTALL_MSG = "Install widget"; +const char * const PKGMGR_UNINSTALL_MSG = "Uninstall widget"; + +const char * const CONFIG_XML = "config.xml"; +const char * const HYBRID_CONFIG_XML = "res/wgt/config.xml"; + +const unsigned int NOFILE_CNT_FOR_INSTALLER = 9999; + +struct free_deleter +{ + void operator()(void* x) + { + free(x); + } +}; + +struct PluginInstallerData +{ + void* wrtInstaller; + std::string pluginPath; +}; + +std::string cutOffFileName(const std::string& path) +{ + size_t found = path.find_last_of("/"); + if (found == std::string::npos) { + return path; + } else { + return path.substr(0, found); + } +} + +bool checkPath(const std::string& path) +{ + struct stat st; + if (0 == stat(path.c_str(), &st) && S_ISDIR(st.st_mode)) { + return true; + } + _E("Cannot access directory [ %s ]", path.c_str()); + return false; +} + +bool checkPaths() +{ + bool if_ok = true; + + if_ok &= (checkPath(cutOffFileName(GlobalConfig::GetWrtDatabaseFilePath()))); + if_ok &= (checkPath(GlobalConfig::GetDevicePluginPath())); + if_ok &= (checkPath(GlobalConfig::GetUserInstalledWidgetPath())); + if_ok &= (checkPath(GlobalConfig::GetUserPreloadedWidgetPath())); + + return if_ok; +} + +} // namespace anonymous + +WrtInstaller::WrtInstaller(int argc, char **argv) : + Application(argc, argv, "backend", false), + DPL::TaskDecl(this), + m_packagePath(), + m_initialized(false), + m_numPluginsToInstall(0), + m_totalPlugins(0), + m_returnStatus(-1), + m_sendPkgSig(false), + m_startupPluginInstallation(false) +{ + Touch(); + _D("App Created"); +} + +WrtInstaller::~WrtInstaller() +{ + _D("App Finished"); +} + +int WrtInstaller::getReturnStatus() const +{ + return m_returnStatus; +} + +void WrtInstaller::OnStop() +{ + _D("Stopping Dummy Client"); +} + +void WrtInstaller::OnCreate() +{ + _D("Creating DummyClient"); + + //pm lock + power_lock_state(POWER_STATE_SCREEN_OFF, 60*1000); + + showArguments(); + + AddStep(&WrtInstaller::initStep); + + std::string arg = m_argv[0]; + + using namespace PackageManager; + + auto pkgmgrSignal = std::shared_ptr(new PackageManager::PkgmgrSignal()); + + pkgmgrSignalInterface = + std::static_pointer_cast( + std::shared_ptr( + new PackageManager::PkgmgrSignalDummy())); + + if (arg.empty()) { + return showHelpAndQuit(); + } + + installNewPlugins(); + + if (arg.find("wrt-installer") != std::string::npos) { + if (m_argc <= 1) { + return showHelpAndQuit(); + } + + arg = m_argv[1]; + if (arg == "-h" || arg == "--help") { + if (m_argc != 2) { + return showHelpAndQuit(); + } + + // Just show help + return showHelpAndQuit(); + } else if (arg == "-p" || arg == "--install-plugins") { + if (m_argc != 2) { + return showHelpAndQuit(); + } + + if (!m_startupPluginInstallation) { + AddStep(&WrtInstaller::installPluginsStep); + } else { + _D("Plugin installation alredy started"); + } + } else if (arg == "-i" || arg == "--install") { + if (m_argc != 3) { + return showHelpAndQuit(); + } + + struct stat info; + if (-1 != stat(m_argv[2], &info) && S_ISDIR(info.st_mode)) { + _D("Installing package directly from directory"); + m_installMode.extension = InstallMode::ExtensionType::DIR; + } else { + _D("Installing from regular location"); + m_installMode.extension = InstallMode::ExtensionType::WGT; + } + m_packagePath = m_argv[2]; + m_sendPkgSig = true; + pkgmgrSignal->initialize(m_argc, m_argv); + pkgmgrSignalInterface = std::static_pointer_cast(pkgmgrSignal); + AddStep(&WrtInstaller::installStep); + } else if (arg == "-ip" || arg == "--install-preload") { + _D("Install preload web app"); + if (m_argc != 3) { + return showHelpAndQuit(); + } + m_packagePath = m_argv[2]; + m_installMode.installTime = InstallMode::InstallTime::PRELOAD; + m_installMode.rootPath = InstallMode::RootPath::RO; + m_installMode.removable = false; + AddStep(&WrtInstaller::installStep); + } else if (arg == "-ipw" || arg == "--install-preload-writable") { + _D("Install preload web application to writable storage"); + if (m_argc != 3) { + return showHelpAndQuit(); + } + m_packagePath = m_argv[2]; + m_installMode.installTime = InstallMode::InstallTime::PRELOAD; + m_installMode.rootPath = InstallMode::RootPath::RW; + m_installMode.removable = true; + AddStep(&WrtInstaller::installStep); + } else if (arg == "-c" || arg == "--csc-update") { + // "path=/opt/system/csc/Ozq2iEG15R-2.0.0-arm.wgt:op=install:removable=true" + _D("Install & uninstall by csc configuration"); + if (m_argc != 3) { + return showHelpAndQuit(); + } + m_installMode.installTime = InstallMode::InstallTime::CSC; + std::string configuration = m_argv[2]; + + CommandParser::CscOption option; + if (!CommandParser::CscCommandParser(configuration, option)) { + return showHelpAndQuit(); + } + + if (0 == option.operation.compare(Command::VALUE_INSTALL)) { + m_installMode.extension = InstallMode::ExtensionType::WGT; + m_packagePath = option.path; + m_installMode.removable = option.removable; + m_installMode.cscPath = m_argv[2]; + _D("operation = %s", option.operation.c_str()); + _D("path = %s", m_packagePath.c_str()); + _D("removable = %d", m_installMode.removable); + _D("csc Path = %s", m_installMode.cscPath.c_str()); + AddStep(&WrtInstaller::installStep); + } else if (0 == option.operation.compare(Command::VALUE_UNINSTALL)){ + m_packagePath = option.path; + _D("operation = %s", option.operation.c_str()); + _D("path = %s", m_packagePath.c_str()); + AddStep(&WrtInstaller::unistallWgtFileStep); + } else { + _E("Unknown operation : %s", option.operation.c_str()); + return showHelpAndQuit(); + } + } else if (arg == "-un" || arg == "--uninstall-name") { + if (m_argc != 3) { + return showHelpAndQuit(); + } + m_name = m_argv[2]; + m_sendPkgSig = true; + m_argv[1] = (char*)"-d"; + pkgmgrSignal->initialize(m_argc, m_argv); + pkgmgrSignalInterface = std::static_pointer_cast(pkgmgrSignal); + AddStep(&WrtInstaller::uninstallPkgNameStep); + } else if (arg == "-up" || arg == "--uninstall-packagepath") { + if (m_argc != 3) { + return showHelpAndQuit(); + } + m_packagePath = m_argv[2]; + AddStep(&WrtInstaller::unistallWgtFileStep); + } else if (arg == "-r" || arg == "--reinstall") { + if (m_argc != 3) { + return showHelpAndQuit(); + } + _D("Installing package directly from directory"); + m_installMode.command = InstallMode::Command::REINSTALL; + m_installMode.extension = InstallMode::ExtensionType::DIR; + m_packagePath = m_argv[2]; + m_sendPkgSig = true; + pkgmgrSignal->initialize(m_argc, m_argv); + pkgmgrSignalInterface = std::static_pointer_cast(pkgmgrSignal); + AddStep(&WrtInstaller::installStep); + } else if (arg == "-f" || arg == "--fota") { + // "path=8HPzsUYyNZ:op=install" + _D("Install & uninstall by fota"); + if (m_argc != 3) { + return showHelpAndQuit(); + } + std::string configuration = m_argv[2]; + CommandParser::FotaOption option; + if (!CommandParser::FotaCommandParser(configuration, option)) { + return showHelpAndQuit(); + } + + if ((0 == option.operation.compare(Command::VALUE_INSTALL)) || + (0 == option.operation.compare(Command::VALUE_UPGRADE)) || + (0 == option.operation.compare(Command::VALUE_UPDATE))) { + _D("FOTA ... Installation"); + m_name = option.pkgId; + m_packagePath += + std::string(WrtDB::GlobalConfig::GetUserPreloadedWidgetPath()) + + "/" + option.pkgId; + _D("package id = %s", m_name.c_str()); + _D("operation = %s", option.operation.c_str()); + _D("package path = %s", m_packagePath.c_str()); + + m_installMode.installTime = InstallMode::InstallTime::FOTA; + m_installMode.rootPath = InstallMode::RootPath::RO; + m_installMode.extension = InstallMode::ExtensionType::DIR; + AddStep(&WrtInstaller::installStep); + } else if (0 == option.operation.compare(Command::VALUE_UNINSTALL)){ + _D("FOTA ... Uninstallation"); + m_name = option.pkgId; + _D("package id = %s", m_name.c_str()); + AddStep(&WrtInstaller::uninstallPkgNameStep); + } else { + _E("Unknown operation : %s", option.operation.c_str()); + return showHelpAndQuit(); + } + } else if (arg == "-b" || arg == "--recovery") { + getRecoveryPackageId(m_name); + _D("m_name : %s", m_name.c_str()); + + if (!m_name.empty()) { + pkgmgrinfo_pkginfo_h handle = NULL; + if (0 == pkgmgrinfo_pkginfo_get_pkginfo(m_name.c_str(), &handle)) { + m_installMode.command = InstallMode::Command::RECOVERY; + m_installMode.extension = InstallMode::ExtensionType::DIR; + AddStep(&WrtInstaller::installStep); + } else { + _D("package id = %s", m_name.c_str()); + AddStep(&WrtInstaller::uninstallPkgNameStep); + } + } + } else { + return showHelpAndQuit(); + } + } else if (arg.find("backend") != std::string::npos) { + m_sendPkgSig = true; + pkgmgrSignal->initialize(m_argc, m_argv); + PkgmgrSignal::RequestType reqType = pkgmgrSignal->getRequestedType(); + pkgmgrSignalInterface = std::static_pointer_cast(pkgmgrSignal); + + switch (reqType) { + case PackageManager::PkgmgrSignal::RequestType::INSTALL: + m_packagePath = m_argv[4]; + if (6 < m_argc) { + m_name = std::string(m_argv[6]); + } + + struct stat info; + if (-1 != stat(m_argv[4], &info) && S_ISDIR(info.st_mode)) { + _D("Installing package directly from directory"); + m_installMode.extension = InstallMode::ExtensionType::DIR; + } else { + _D("Installing from regular location"); + m_installMode.extension = InstallMode::ExtensionType::WGT; + } + AddStep(&WrtInstaller::installStep); + break; + case PackageManager::PkgmgrSignal::RequestType::UNINSTALL: + { + m_name = m_argv[4]; + pkgmgrinfo_pkginfo_h handle = NULL; + bool preload = false; + bool system = false; + bool removable = true; + bool update = false; + char *cscPath = NULL; + + if (0 == pkgmgrinfo_pkginfo_get_pkginfo(m_name.c_str(), &handle)) { + if (0 > pkgmgrinfo_pkginfo_is_preload(handle, &preload)) { + _E("Can't get package information : %s", m_name.c_str()); + } + if (0 > pkgmgrinfo_pkginfo_is_system(handle, &system)) { + _E("Can't get package information : %s", m_name.c_str()); + } + if (0 > pkgmgrinfo_pkginfo_is_removable(handle, &removable)) { + _E("Can't get package information : %s", m_name.c_str()); + } + if (0 > pkgmgrinfo_pkginfo_is_update(handle, &update)) { + _E("Can't get package information about update : %s", m_name.c_str()); + } + if (0 > pkgmgrinfo_pkginfo_get_csc_path(handle, &cscPath)) { + _E("Can't get package information about update : %s", m_name.c_str()); + } + } + + _D("preload app : %d", preload); + _D("system app : %d", system); + _D("removable app : %d", removable); + _D("update : %d", update); + _D("csc path : %s", cscPath); + + if (preload && update) { + if (system) { + AddStep(&WrtInstaller::removeUpdateStep); + } else if (setInitialCSC(cscPath)) { + AddStep(&WrtInstaller::uninstallPkgNameStep); + AddStep(&WrtInstaller::installStep); + } else if (removable) { + AddStep(&WrtInstaller::uninstallPkgNameStep); + } + } else { + AddStep(&WrtInstaller::uninstallPkgNameStep); + } + pkgmgrinfo_pkginfo_destroy_pkginfo(handle); + break; + } + case PackageManager::PkgmgrSignal::RequestType::REINSTALL: + m_packagePath = m_argv[4]; + m_installMode.command = InstallMode::Command::REINSTALL; + m_installMode.extension = InstallMode::ExtensionType::DIR; + AddStep(&WrtInstaller::installStep); + break; + default: + _D("Not available type"); + break; + } + } + + AddStep(&WrtInstaller::shutdownStep); + DPL::Event::ControllerEventHandler:: + PostEvent( + WRTInstallerNS::NextStepEvent()); +} + +void WrtInstaller::OnReset(bundle* /*b*/) +{ + _D("OnReset"); +} + +void WrtInstaller::OnTerminate() +{ + _D("Wrt Shutdown now"); + + //pm unlock + power_unlock_state(POWER_STATE_SCREEN_OFF); + + PluginUtils::unlockPluginInstallation( + m_installMode.installTime == InstallMode::InstallTime::PRELOAD); + if (m_initialized) { + try { + _D("DEINITIALIZING WRT INSTALLER..."); + // Installer termination + CONTROLLER_POST_SYNC_EVENT( + Logic::InstallerController, + InstallerControllerEvents:: + TerminateEvent()); + InstallerMainThreadSingleton::Instance().DetachDatabases(); + I18n::DB::Interface::detachDatabase(); + + // This must be done after DetachDatabase + ValidationCore::VCoreDeinit(); + + // Global deinit check + _D("Cleanup libxml2 global values."); + xmlCleanupParser(); + } catch (const DPL::Exception& ex) { + _E("Internal Error during Shutdown:"); + DPL::Exception::DisplayKnownException(ex); + } + } +} + +void WrtInstaller::showHelpAndQuit() +{ + printf("Usage: wrt-installer [OPTION]... [WIDGET: ID/NAME/PATH]...\n" + "Operate with WebRuntime daemon: install, uninstall" + " and launch widgets.\n" + "Query list of installed widgets and setup up debugging support.\n" + "\n" + "Exactly one option must be selected.\n" + "Mandatory arguments to long options are mandatory for short " + "options too.\n" + " -h, --help show this help\n" + " -p, --install-plugins install plugins\n" + " -i, --install " + "install or update widget package for given path\n" + " -c, --csc-update " + "install or uninstall by CSC configuration \n" + " -un, --uninstall-name " + "uninstall widget for given package name\n" + " -up, --uninstall-packagepath " + "uninstall widget for given package file path\n" + " -r, --reinstall " + "reinstall mode for sdk (this is NOT normal reinstallation/update)\n" + "\n"); + + Quit(); +} + +void WrtInstaller::showArguments() +{ + fprintf(stderr, + "===========================================================\n"); + fprintf(stderr, "# wrt-installer #\n"); + fprintf(stderr, "# argc [%d]\n", m_argc); + for (int i = 0; i < m_argc; i++) { + fprintf(stderr, "# argv[%d] = [%s]\n", i, m_argv[i]); + } + fprintf(stderr, + "===========================================================\n"); + // for dlog + _D("==========================================================="); + _D("# wrt-installer #"); + _D("# argc %d", m_argc); + for (int i = 0; i < m_argc; i++) { + _D("# argv[%d] = %s", i, m_argv[i]); + } + _D("==========================================================="); + +} + +void WrtInstaller::OnEventReceived(const WRTInstallerNS::QuitEvent& /*event*/) +{ + _D("Quiting"); + + if (m_initialized) { + _D("Wrt Shutdown now"); + SwitchToStep(&WrtInstaller::shutdownStep); + DPL::Event::ControllerEventHandler:: + PostEvent( + WRTInstallerNS::NextStepEvent()); + } else { + _D("Quiting application"); + return Quit(); + } +} + +void WrtInstaller::OnEventReceived( + const WRTInstallerNS::NextStepEvent& /*event*/) +{ + _D("Executing next step"); + NextStep(); +} + +void WrtInstaller::OnEventReceived( + const WRTInstallerNS::InstallPluginEvent& /*event*/) +{ + PluginInstallerData* privateData = new PluginInstallerData; + privateData->wrtInstaller = this; + + if (!(*m_pluginsPaths).empty()) { + privateData->pluginPath = (*m_pluginsPaths).front(); + (*m_pluginsPaths).pop_front(); + + _D("INSTALL PLUGIN: %s", privateData->pluginPath.c_str()); + //Private data for status callback + //Resource is free in pluginInstallFinishedCallback + InstallerCallbacksTranslate::PluginStatusCallbackStruct* + callbackStruct = + new InstallerCallbacksTranslate::PluginStatusCallbackStruct( + privateData, &staticWrtPluginInstallationCallback, &staticWrtPluginInstallProgressCb); + + CONTROLLER_POST_EVENT( + Logic::InstallerController, + InstallerControllerEvents::InstallPluginEvent( + privateData->pluginPath, + PluginInstallerStruct( + InstallerCallbacksTranslate:: + pluginInstallFinishedCallback, + InstallerCallbacksTranslate:: + installProgressCallback, callbackStruct))); + } else { + delete privateData; + } +} + +void WrtInstaller::initStep() +{ + try { + _D("INITIALIZING WRT INSTALLER..."); + + // Touch InstallerController Singleton + InstallerMainThreadSingleton::Instance().TouchArchitecture(); + + // Check paths + if (!checkPaths()) { + makeStatusOfWrtInit(WRT_INSTALLER_ERROR_FATAL_ERROR); + return; + } + + // Initialize ValidationCore - this must be done before AttachDatabases + ValidationCore::VCoreInit( + std::string(GlobalConfig::GetFingerprintListFile()), + std::string(GlobalConfig::GetFingerprintListSchema()), + std::string(GlobalConfig::GetVCoreDatabaseFilePath())); + + InstallerMainThreadSingleton::Instance().AttachDatabases(); + + _D("Prepare libxml2 to work in multithreaded program."); + xmlInitParser(); + + // Initialize Language Subtag registry + LanguageSubtagRstTreeSingleton::Instance().Initialize(); + + // Installer init + CONTROLLER_POST_SYNC_EVENT( + Logic::InstallerController, + InstallerControllerEvents:: + InitializeEvent()); + + makeStatusOfWrtInit(WRT_SUCCESS); + } catch (const DPL::Exception& ex) { + _E("Internal Error during Init:"); + DPL::Exception::DisplayKnownException(ex); + makeStatusOfWrtInit(WRT_INSTALLER_ERROR_FATAL_ERROR); + } +} + +void WrtInstaller::installStep() +{ + std::unique_ptr packagePath(canonicalize_file_name( + m_packagePath.c_str())); + + if (InstallMode::InstallTime::PRELOAD == m_installMode.installTime) { + DPL::Log::OldStyleLogProvider *oldStyleProvider = + new DPL::Log::OldStyleLogProvider(false, false, false, true, + false, true); + DPL::Log::LogSystemSingleton::Instance().AddProvider(oldStyleProvider); + } + + std::string path = packagePath ? packagePath.get() : m_packagePath.c_str(); + _D("INSTALL WIDGET: %s", path.c_str()); + // Post installation event + CONTROLLER_POST_EVENT( + Logic::InstallerController, + InstallerControllerEvents::InstallWidgetEvent( + path, m_name.c_str(), + Jobs::WidgetInstall::WidgetInstallationStruct( + InstallerCallbacksTranslate::installFinishedCallback, + InstallerCallbacksTranslate::installProgressCallback, + new InstallerCallbacksTranslate::StatusCallbackStruct( + this, &staticWrtStatusCallback, (m_sendPkgSig) + ? &staticWrtInstallProgressCallback : NULL), + m_installMode, pkgmgrSignalInterface))); +} + +void WrtInstaller::installPluginsStep() +{ + _D("Installing plugins ..."); + fprintf(stderr, "Installing plugins ...\n"); + + if (m_startupPluginInstallation) { + _D("Plugin installation started because new plugin package found"); + } else if (!PluginUtils::lockPluginInstallation( + m_installMode.installTime == InstallMode::InstallTime::PRELOAD)) + { + _E("Failed to open plugin installation lock file" + " Plugins are currently installed by other process"); + staticWrtPluginInstallationCallback(WRT_INSTALLER_ERROR_PLUGIN_INSTALLATION_FAILED, + this); + return; + } + + std::string PLUGIN_PATH = std::string(GlobalConfig::GetDevicePluginPath()); + + DIR *dir; + dir = opendir(PLUGIN_PATH.c_str()); + + if (!dir) { + return; + } + + _D("Plugin DIRECTORY IS %s", PLUGIN_PATH.c_str()); + + std::list pluginsPaths; + struct dirent libdir; + struct dirent *result; + int return_code; + errno = 0; + for (return_code = readdir_r(dir, &libdir, &result); + result != NULL && return_code == 0; + return_code = readdir_r(dir, &libdir, &result)) + { + if (strcmp(libdir.d_name, ".") == 0 || + strcmp(libdir.d_name, "..") == 0) + { + continue; + } + + std::string path = PLUGIN_PATH; + path += "/"; + path += libdir.d_name; + + struct stat tmp; + + if (stat(path.c_str(), &tmp) == -1) { + _E("Failed to open file %s", path.c_str()); + continue; + } + + if (!S_ISDIR(tmp.st_mode)) { + _E("Not a directory %s", path.c_str()); + continue; + } + + pluginsPaths.push_back(path); + } + + if (return_code != 0 || errno != 0) { + _E("readdir_r() failed with %s", DPL::GetErrnoString().c_str()); + } + + //set nb of plugins to install + //this value indicate how many callbacks are expected + m_numPluginsToInstall = pluginsPaths.size(); + _D("Plugins to install: %d", m_numPluginsToInstall); + m_pluginsPaths = pluginsPaths; + + m_totalPlugins = m_numPluginsToInstall; + DPL::Event::ControllerEventHandler + ::PostEvent(WRTInstallerNS::InstallPluginEvent()); + + if (-1 == closedir(dir)) { + _E("Failed to close dir: %s with error: %s", PLUGIN_PATH.c_str(), DPL::GetErrnoString().c_str()); + } +} + +void WrtInstaller::uninstallPkgNameStep() +{ + _D("Package name : %s", m_name.c_str()); + + _D("UNINSTALL WIDGET: %s", m_name.c_str()); + // Post uninstallation event + CONTROLLER_POST_EVENT( + Logic::InstallerController, + InstallerControllerEvents::UninstallWidgetEvent( + m_name, + WidgetUninstallationStruct( + InstallerCallbacksTranslate::uninstallFinishedCallback, + InstallerCallbacksTranslate::installProgressCallback, + new InstallerCallbacksTranslate::StatusCallbackStruct( + this, &staticWrtStatusCallback, + (m_sendPkgSig) ? &staticWrtUninstallProgressCallback : NULL), + pkgmgrSignalInterface) + ) + ); +} + +void WrtInstaller::removeUpdateStep() +{ + _D("This web app need to initialize preload app"); + _D("Package name : %s", m_name.c_str()); + + _D("UNINSTALL WIDGET: %s", m_name.c_str()); + // Post uninstallation event + CONTROLLER_POST_EVENT( + Logic::InstallerController, + InstallerControllerEvents::UninstallWidgetEvent( + m_name, + WidgetUninstallationStruct( + InstallerCallbacksTranslate::uninstallFinishedCallback, + InstallerCallbacksTranslate::installProgressCallback, + new InstallerCallbacksTranslate::StatusCallbackStruct( + this, &staticWrtInitializeToPreloadCallback, (m_sendPkgSig) + ? &staticWrtUninstallProgressCallback : NULL), + pkgmgrSignalInterface + ) + ) + ); +} + +bool WrtInstaller::setInitialCSC(std::string cscPath) +{ + _D("This web app need to initialize initial csc app"); + _D("UNINSTALL WIDGET: %s", m_name.c_str()); + _D("csc path: %s", cscPath.c_str()); + + m_installMode.installTime = InstallMode::InstallTime::CSC; + std::string configuration = cscPath; + + CommandParser::CscOption option; + if (!CommandParser::CscCommandParser(configuration, option)) { + _E("Failure command parser"); + return false; + } + + if (0 == option.operation.compare(Command::VALUE_INSTALL)) { + m_installMode.extension = InstallMode::ExtensionType::WGT; + m_packagePath = option.path; + m_installMode.removable = option.removable; + m_installMode.cscPath = cscPath; + _D("operation = %s", option.operation.c_str()); + _D("path = %s", m_packagePath.c_str()); + _D("removable = %d", m_installMode.removable); + _D("csc Path = %s", m_installMode.cscPath.c_str()); + } else { + _E("Unknown operation : %s", option.operation.c_str()); + return false; + } + return true; +} + +void WrtInstaller::unistallWgtFileStep() +{ + _D("Uninstalling widget ..."); + + Try { + // Parse config + ParserRunner parser; + ConfigParserData configInfo; + + // Open zip file + std::unique_ptr zipFile( + new DPL::ZipInput(m_packagePath)); + std::unique_ptr configFile; + + Try { + // Open config.xml file + configFile.reset(zipFile->OpenFile(CONFIG_XML)); + } + Catch(DPL::ZipInput::Exception::OpenFileFailed) + { + // Open config.xml file for hybrid + configFile.reset(zipFile->OpenFile(HYBRID_CONFIG_XML)); + } + + // Extract config + DPL::BinaryQueue buffer; + DPL::AbstractWaitableInputAdapter inputAdapter(configFile.get()); + DPL::AbstractWaitableOutputAdapter outputAdapter(&buffer); + DPL::Copy(&inputAdapter, &outputAdapter); + parser.Parse(&buffer, + ElementParserPtr( + new RootParser(configInfo, + DPL::FromUTF32String( + L"widget")))); + + DPL::OptionalString pkgId = configInfo.tizenPkgId; + if (!!pkgId) { + _D("Pkgid from packagePath : %ls", (*pkgId).c_str()); + _D("UNINSTALL WIDGET: %s", DPL::ToUTF8String(*pkgId).c_str()); + // Post uninstallation event + CONTROLLER_POST_EVENT( + Logic::InstallerController, + InstallerControllerEvents::UninstallWidgetEvent( + DPL::ToUTF8String(*pkgId), + WidgetUninstallationStruct( + InstallerCallbacksTranslate::uninstallFinishedCallback, + InstallerCallbacksTranslate::installProgressCallback, + new InstallerCallbacksTranslate::StatusCallbackStruct( + this, &staticWrtStatusCallback, !m_sendPkgSig + ? &staticWrtUninstallProgressCallback : NULL), + pkgmgrSignalInterface) + ) + ); + + } else { + _E("Fail to uninstalling widget... "); + m_returnStatus = -1; + DPL::Event::ControllerEventHandler:: + PostEvent( + WRTInstallerNS::QuitEvent()); + } + } + Catch(DPL::ZipInput::Exception::OpenFailed) + { + _E("Failed to open widget package"); + printf("failed: widget package does not exist\n"); + m_returnStatus = -1; + DPL::Event::ControllerEventHandler:: + PostEvent( + WRTInstallerNS::QuitEvent()); + } + Catch(DPL::ZipInput::Exception::OpenFileFailed) + { + printf("failed: widget config file does not exist\n"); + _E("Failed to open config.xml file"); + m_returnStatus = -1; + DPL::Event::ControllerEventHandler:: + PostEvent( + WRTInstallerNS::QuitEvent()); + } + Catch(ElementParser::Exception::ParseError) + { + printf("failed: can not parse config file\n"); + _E("Failed to parse config.xml file"); + m_returnStatus = -1; + DPL::Event::ControllerEventHandler:: + PostEvent( + WRTInstallerNS::QuitEvent()); + } + Catch(DPL::Exception) + { + printf("Unknown DPL exception\n"); + _E("Unknown DPL exception"); + m_returnStatus = -1; + DPL::Event::ControllerEventHandler:: + PostEvent( + WRTInstallerNS::QuitEvent()); + } +} + +void WrtInstaller::shutdownStep() +{ + _D("Closing Wrt connection ..."); + if (m_initialized) { + try { + _D("DEINITIALIZING WRT INSTALLER..."); + // Installer termination + CONTROLLER_POST_SYNC_EVENT( + Logic::InstallerController, + InstallerControllerEvents:: + TerminateEvent()); + + InstallerMainThreadSingleton::Instance().DetachDatabases(); + + // This must be done after DetachDatabase + ValidationCore::VCoreDeinit(); + + // Global deinit check + _D("Cleanup libxml2 global values."); + xmlCleanupParser(); + } catch (const DPL::Exception& ex) { + _E("Internal Error during Shutdown:"); + DPL::Exception::DisplayKnownException(ex); + } + m_initialized = false; + DPL::Event::ControllerEventHandler:: + PostEvent( + WRTInstallerNS::QuitEvent()); + } +} + +void WrtInstaller::makeStatusOfWrtInit(WrtErrStatus status) +{ + if (status == WRT_SUCCESS) { + _D("Init succesfull"); + m_initialized = true; + m_returnStatus = 0; + + DPL::Event::ControllerEventHandler + ::PostEvent(WRTInstallerNS::NextStepEvent()); + } else { + _E("Init unsuccesfull"); + m_returnStatus = -1; + DPL::Event::ControllerEventHandler:: + PostEvent( + WRTInstallerNS::QuitEvent()); + } +} + +void WrtInstaller::staticWrtInitializeToPreloadCallback(std::string tizenId, WrtErrStatus + status, void* userdata) +{ + WrtInstaller *This = static_cast(userdata); + Assert(This); + + std::string printMsg = "uninstallation"; + + if (WRT_SUCCESS != status) { + // Failure + _E("Step failed"); + This->m_returnStatus = 1; + + This->showErrorMsg(status, tizenId, printMsg); + + This->DPL::Event::ControllerEventHandler + ::PostEvent(WRTInstallerNS::QuitEvent()); + } else { + InstallMode mode; + mode.extension = InstallMode::ExtensionType::DIR; + mode.installTime = InstallMode::InstallTime::PRELOAD; + mode.rootPath = InstallMode::RootPath::RO; + std::string packagePath = + std::string(WrtDB::GlobalConfig::GetUserPreloadedWidgetPath()) + + "/" + This->m_name; + + if (InstallMode::InstallTime::PRELOAD == This->m_installMode.installTime) { + DPL::Log::OldStyleLogProvider *oldStyleProvider = + new DPL::Log::OldStyleLogProvider(false, false, false, true, + false, true); + DPL::Log::LogSystemSingleton::Instance().AddProvider(oldStyleProvider); + } + + _D("INSTALL WIDGET: %s", packagePath.c_str()); + // Post installation event + CONTROLLER_POST_EVENT( + Logic::InstallerController, + InstallerControllerEvents::InstallWidgetEvent( + packagePath, tizenId.c_str(), Jobs::WidgetInstall::WidgetInstallationStruct( + InstallerCallbacksTranslate::installFinishedCallback, + InstallerCallbacksTranslate::installProgressCallback, + new InstallerCallbacksTranslate::StatusCallbackStruct( + This, &staticWrtInitPreloadStatusCallback, NULL), + mode, + This->pkgmgrSignalInterface))); + } +} + +void WrtInstaller::staticWrtInitPreloadStatusCallback(std::string tizenId, + WrtErrStatus status, + void* userdata) +{ + WrtInstaller *This = static_cast(userdata); + Assert(This); + + std::string printMsg = "initialization"; + + if (WRT_SUCCESS != status) { + // Failure + _E("Step failed"); + This->m_returnStatus = status; + + This->showErrorMsg(status, tizenId, printMsg); + + This->DPL::Event::ControllerEventHandler + ::PostEvent(WRTInstallerNS::QuitEvent()); + } else { + fprintf(stderr, + "## wrt-installer : %s %s was successful.\n", + tizenId.c_str(), + printMsg.c_str()); + _D("Status succesfull"); + This->m_returnStatus = 0; + + This->DPL::Event::ControllerEventHandler + ::PostEvent(WRTInstallerNS::NextStepEvent()); + } +} + +void WrtInstaller::staticWrtStatusCallback(std::string tizenId, + WrtErrStatus status, + void* userdata) +{ + WrtInstaller *This = static_cast(userdata); + Assert(This); + + Step current = This->GetCurrentStep(); + std::string printMsg; + + if (current == &WrtInstaller::installStep) { + printMsg = "installation"; + } else if (current == &WrtInstaller::uninstallPkgNameStep || + current == &WrtInstaller::unistallWgtFileStep) + { + printMsg = "uninstallation"; + } + + if (WRT_SUCCESS != status) { + // Failure + _E("Step failed"); + This->m_returnStatus = status; + + This->DPL::Event::ControllerEventHandler + ::PostEvent(WRTInstallerNS::QuitEvent()); + + This->showErrorMsg(status, tizenId, printMsg); + } else { + fprintf(stderr, + "## wrt-installer : %s %s was successful.\n", + tizenId.c_str(), + printMsg.c_str()); + _D("Status succesfull"); + This->m_returnStatus = 0; + + if (This->m_installMode.installTime == InstallMode::InstallTime::PRELOAD && + !This->m_packagePath.empty()) + { + _D("This widget is preloaded so it will be removed : %s", This->m_packagePath.c_str()); + if (!WrtUtilRemove(This->m_packagePath)) { + _E("Failed to remove %s", This->m_packagePath.c_str()); + } + } + + This->DPL::Event::ControllerEventHandler + ::PostEvent(WRTInstallerNS::NextStepEvent()); + } +} + +void WrtInstaller::showErrorMsg(WrtErrStatus status, std::string tizenId, + std::string printMsg) +{ + switch (status) { + case WRT_INSTALLER_ERROR_PACKAGE_NOT_FOUND: + fprintf(stderr, "## wrt-installer : %s %s has failed - widget package does not exist\n", + tizenId.c_str(), printMsg.c_str()); + break; + + case WRT_INSTALLER_ERROR_PACKAGE_INVALID: + fprintf(stderr, "## wrt-installer : %s %s has failed - invalid widget package\n", + tizenId.c_str(), printMsg.c_str()); + break; + + case WRT_INSTALLER_ERROR_PACKAGE_LOWER_VERSION: + fprintf(stderr, "## wrt-installer : %s %s has failed - given" + " version is lower than existing version\n", + tizenId.c_str(), printMsg.c_str()); + break; + + case WRT_INSTALLER_ERROR_MANIFEST_NOT_FOUND: + fprintf(stderr, "## wrt-installer : %s %s has failed - manifest" + " file doesn't find in package.\n", + tizenId.c_str(), printMsg.c_str()); + break; + + case WRT_INSTALLER_ERROR_MANIFEST_INVALID: + fprintf(stderr, "## wrt-installer : %s %s has failed - " + "invalid manifestx.xml\n", + tizenId.c_str(), printMsg.c_str()); + break; + + case WRT_INSTALLER_CONFIG_NOT_FOUND: + fprintf(stderr, "## wrt-installer : %s %s has failed - " + "config.xml does not exist\n", + tizenId.c_str(), printMsg.c_str()); + break; + + case WRT_INSTALLER_ERROR_CONFIG_INVALID: + fprintf(stderr, "## wrt-installer : %s %s has failed - " + "invalid config.xml\n", + tizenId.c_str(), printMsg.c_str()); + break; + + case WRT_INSTALLER_ERROR_SIGNATURE_NOT_FOUND: + fprintf(stderr, "## wrt-installer : %s %s has failed - " + "signature doesn't exist in package.\n", + tizenId.c_str(), printMsg.c_str()); + break; + + case WRT_INSTALLER_ERROR_SIGNATURE_INVALID: + fprintf(stderr, "## wrt-installer : %s %s has failed - " + "invalid signature.\n", + tizenId.c_str(), printMsg.c_str()); + break; + + case WRT_INSTALLER_ERROR_SIGNATURE_VERIFICATION_FAILED: + fprintf(stderr, "## wrt-installer : %s %s has failed - " + "signature verification failed.\n", + tizenId.c_str(), printMsg.c_str()); + break; + + case WRT_INSTALLER_ERROR_ROOT_CERTIFICATE_NOT_FOUND: + fprintf(stderr, "## wrt-installer : %s %s has failed - " + "root certificate could not find.\n", + tizenId.c_str(), printMsg.c_str()); + break; + + case WRT_INSTALLER_ERROR_CERTIFICATION_INVAID: + fprintf(stderr, "## wrt-installer : %s %s has failed - " + "invalid certification.\n", + tizenId.c_str(), printMsg.c_str()); + break; + + case WRT_INSTALLER_ERROR_CERTIFICATE_CHAIN_VERIFICATION_FAILED: + fprintf(stderr, "## wrt-installer : %s %s has failed - " + "certificate chain verification failed.\n", + tizenId.c_str(), printMsg.c_str()); + break; + + case WRT_INSTALLER_ERROR_CERTIFICATE_EXPIRED: + fprintf(stderr, "## wrt-installer : %s %s has failed - " + "certificate expired.\n", + tizenId.c_str(), printMsg.c_str()); + break; + + case WRT_INSTALLER_ERROR_INVALID_PRIVILEGE: + fprintf(stderr, "## wrt-installer : %s %s has failed - " + "invalid privilege\n", + tizenId.c_str(), printMsg.c_str()); + break; + + case WRT_INSTALLER_ERROR_PRIVILEGE_LEVEL_VIOLATION: + fprintf(stderr, "## wrt-installer : %s %s has failed - " + "privilege level violation\n", + tizenId.c_str(), printMsg.c_str()); + break; + + case WRT_INSTALLER_ERROR_MENU_ICON_NOT_FOUND: + fprintf(stderr, "## wrt-installer : %s %s has failed - " + "menu icon could not find\n", + tizenId.c_str(), printMsg.c_str()); + break; + + case WRT_INSTALLER_ERROR_FATAL_ERROR: + fprintf(stderr, "## wrt-installer : %s %s has failed - " + "fatal error\n", + tizenId.c_str(), printMsg.c_str()); + break; + + case WRT_INSTALLER_ERROR_OUT_OF_STORAGE: + fprintf(stderr, "## wrt-installer : %s %s has failed - " + "out of storage\n", + tizenId.c_str(), printMsg.c_str()); + break; + + case WRT_INSTALLER_ERROR_OUT_OF_MEMORY: + fprintf(stderr, "## wrt-installer : %s %s has failed - " + "out of memory\n", + tizenId.c_str(), printMsg.c_str()); + break; + + case WRT_INSTALLER_ERROR_ARGUMENT_INVALID: + fprintf(stderr, "## wrt-installer : %s %s has failed - " + "invalid argument\n", + tizenId.c_str(), printMsg.c_str()); + break; + + case WRT_INSTALLER_ERROR_PACKAGE_ALREADY_INSTALLED: + fprintf(stderr, "## wrt-installer : %s %s has failed - " + "package already installed\n", + tizenId.c_str(), printMsg.c_str()); + break; + + case WRT_INSTALLER_ERROR_ACE_CHECK_FAILED: + fprintf(stderr, "## wrt-installer : %s %s has failed - " + "ace check failure\n", + tizenId.c_str(), printMsg.c_str()); + break; + + case WRT_INSTALLER_ERROR_MANIFEST_CREATE_FAILED: + fprintf(stderr, "## wrt-installer : %s %s has failed - " + "to create manifest failed\n", + tizenId.c_str(), printMsg.c_str()); + break; + + case WRT_INSTALLER_ERROR_ENCRYPTION_FAILED: + fprintf(stderr, "## wrt-installer : %s %s has failed - " + "encryption of resource failed\n", + tizenId.c_str(), printMsg.c_str()); + break; + + case WRT_INSTALLER_ERROR_INSTALL_OSP_SERVCIE: + fprintf(stderr, "## wrt-installer : %s %s has failed - " + "installation of osp service failed\n", + tizenId.c_str(), printMsg.c_str()); + break; + + case WRT_INSTALLER_ERROR_UNINSTALLATION_FAILED: + fprintf(stderr, "## wrt-installer : %s %s has failed - " + "widget uninstallation failed\n", + tizenId.c_str(), printMsg.c_str()); + break; + + + case WRT_INSTALLER_ERROR_UNKNOWN: + fprintf(stderr,"## wrt-installer : %s %s has failed - unknown error\n", + tizenId.c_str(), printMsg.c_str()); + break; + + default: + break; + } + +} + +void WrtInstaller::staticWrtPluginInstallationCallback(WrtErrStatus status, + void* userdata) +{ + Assert(userdata); + + PluginInstallerData* data = static_cast(userdata); + + WrtInstaller *This = static_cast(data->wrtInstaller); + + std::string path = std::string(data->pluginPath); + delete data; + + This->m_numPluginsToInstall--; + _D("Plugins to install: %d", This->m_numPluginsToInstall); + + if (This->m_numPluginsToInstall < 1) { + _D("All plugins installation completed"); + fprintf(stderr, "All plugins installation completed.\n"); + + //remove installation request + if (!PluginUtils::removeInstallationRequiredFlag()) { + _D("Failed to remove file initializing plugin installation"); + } + + //remove lock file + if (!PluginUtils::unlockPluginInstallation( + This->m_installMode.installTime == InstallMode::InstallTime::PRELOAD)) + { + _D("Failed to remove installation lock"); + } + + This->DPL::Event::ControllerEventHandler + ::PostEvent(WRTInstallerNS::NextStepEvent()); + } else { + This->DPL::Event::ControllerEventHandler:: + PostEvent( + WRTInstallerNS::InstallPluginEvent()); + } + + if (WRT_SUCCESS == status) { + This->m_returnStatus = 0; + fprintf(stderr, + "## wrt-installer : plugin installation successfull [%s]\n", + path.c_str()); + _D("One plugin Installation succesfull: %s", path.c_str()); + return; + } + + // Failure + _W("One of the plugins installation failed!: %s", path.c_str()); + + switch (status) { + case WRT_INSTALLER_ERROR_PLUGIN_INSTALLATION_FAILED: + _E("failed: plugin installation failed\n"); + break; + + case WRT_INSTALLER_ERROR_UNKNOWN: + _E("failed: unknown error\n"); + break; + + default: + break; + } +} + +void WrtInstaller::staticWrtPluginInstallProgressCb(float percent, + const char* description, + void* userdata) +{ + PluginInstallerData* data = static_cast(userdata); + + std::string path = std::string(data->pluginPath); + + _D("Plugin Installation: %s progress: %2.0f description: %s", path.c_str(), percent, description); +} + +void WrtInstaller::staticWrtInstallProgressCallback(float percent, + const char* description, + void* /*userdata*/) +{ + //WrtInstaller *This = static_cast(userdata); + _D(" progress: %2.0f description: %s", percent, description); +} +void WrtInstaller::staticWrtUninstallProgressCallback(float percent, + const char* description, + void* /*userdata*/) +{ + //WrtInstaller *This = static_cast(userdata); + _D(" progress: %2.0f description: %s", percent, description); +} + +void WrtInstaller::installNewPlugins() +{ + _D("Install new plugins"); + + if (!PluginUtils::lockPluginInstallation( + m_installMode.installTime == InstallMode::InstallTime::PRELOAD)) + { + _D("Lock NOT created"); + return; + } + + if (!PluginUtils::checkPluginInstallationRequired()) { + _D("Plugin installation not required"); + PluginUtils::unlockPluginInstallation( + m_installMode.installTime == InstallMode::InstallTime::PRELOAD); + return; + } + + m_startupPluginInstallation = true; + AddStep(&WrtInstaller::installPluginsStep); +} + +void WrtInstaller::getRecoveryPackageId(std::string &pkgId) +{ + _D("getRecoveryPackageId"); + std::string folderPath = + std::string(WrtDB::GlobalConfig::GetTempInstallInfoPath()) + "/"; + + DIR* dir = opendir(folderPath.c_str()); + if (NULL == dir) { + return; + } + + struct dirent dEntry; + struct dirent *dEntryResult; + int return_code; + + do { + struct stat statInfo; + return_code = readdir_r(dir, &dEntry, &dEntryResult); + if (dEntryResult != NULL && return_code == 0) { + std::string fileName = dEntry.d_name; + std::string fullName = folderPath + "/" + fileName; + + if (stat(fullName.c_str(), &statInfo) != 0) { + closedir(dir); + return; + } + + if (S_ISDIR(statInfo.st_mode)) { + if (("." == fileName) || (".." == fileName)) { + continue; + } + } else { + pkgId = fileName; + if (0 != unlink(fullName.c_str())) { + _E("Fail to delete : %s", fullName.c_str()); + } + } + } + } while (dEntryResult != NULL && return_code == 0); + closedir(dir); +} + +#if 0 +void shell(const char* cmd) { + char buf[256]; + FILE *fp; + + _E("### %s ###", cmd); + fp = popen(cmd, "r"); + if (fp == NULL) { + _E("error: fp is NULL"); + } else { + while(fgets(buf, 256, fp) != NULL) { + _E("%s", buf); + } + pclose(fp); + } +} +#endif + +int main(int argc, char *argv[]) +{ + UNHANDLED_EXCEPTION_HANDLER_BEGIN + { + DPL::Log::LogSystemSingleton::Instance().SetTag("WRT_INSTALLER"); + + // Output on stdout will be flushed after every newline character, + // even if it is redirected to a pipe. This is useful for running + // from a script and parsing output. + // (Standard behavior of stdlib is to use full buffering when + // redirected to a pipe, which means even after an end of line + // the output may not be flushed). + setlinebuf(stdout); + + // Check and re-set the file open limitation + struct rlimit rlim; + if (getrlimit(RLIMIT_NOFILE, &rlim) != -1) { + _D("RLIMIT_NOFILE sft(%d)", rlim.rlim_cur); + _D("RLIMIT_NOFILE hrd(%d)", rlim.rlim_max); + + if (rlim.rlim_cur < NOFILE_CNT_FOR_INSTALLER) { + rlim.rlim_cur = NOFILE_CNT_FOR_INSTALLER; + rlim.rlim_max = NOFILE_CNT_FOR_INSTALLER; + if (setrlimit(RLIMIT_NOFILE, &rlim) == -1) { + _E("setrlimit is fail!!"); + } + } + } else { + _E("getrlimit is fail!!"); + } + + WrtInstaller app(argc, argv); + int ret = app.Exec(); + // In FOTA environment, appcore will return -1 due to /tmp is read-only. + if (ret != 0) { + app.OnCreate(); + elm_run(); + app.OnTerminate(); + } + _D("App returned: %d", ret); + ret = app.getReturnStatus(); + _D("WrtInstaller returned: %d", ret); + return ret; + } + UNHANDLED_EXCEPTION_HANDLER_END +} diff --git a/src_wearable/wrt-installer/wrt-installer.h b/src_wearable/wrt-installer/wrt-installer.h new file mode 100755 index 0000000..a60d36c --- /dev/null +++ b/src_wearable/wrt-installer/wrt-installer.h @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file wrt-installer.h + * @version 1.0 + * @brief Implementation file for installer + */ +#ifndef WRT_INSTALLER_H +#define WRT_INSTALLER_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace WRTInstallerNS { //anonymous +DECLARE_GENERIC_EVENT_0(QuitEvent) +DECLARE_GENERIC_EVENT_0(NextStepEvent) +DECLARE_GENERIC_EVENT_0(InstallPluginEvent) +} + +typedef void (*ShowResultCallback)(void *data, Evas_Object *obj, + void *event_info); +class WrtInstaller : + public DPL::Application, + private DPL::Event::Controller:: + Type>, + public DPL::TaskDecl +{ + public: + WrtInstaller(int argc, + char **argv); + virtual ~WrtInstaller(); + + int getReturnStatus() const; + + virtual void OnStop(); + virtual void OnCreate(); + virtual void OnReset(bundle *b); + virtual void OnTerminate(); + + private: + void showHelpAndQuit(); + void showArguments(); + + // Events + virtual void OnEventReceived(const WRTInstallerNS::QuitEvent &event); + virtual void OnEventReceived(const WRTInstallerNS::NextStepEvent& event); + virtual void OnEventReceived( + const WRTInstallerNS::InstallPluginEvent& event); + + // Installation steps + void initStep(); + void installStep(); + void installPluginsStep(); + void uninstallPkgNameStep(); + void unistallWgtFileStep(); + void removeUpdateStep(); + void shutdownStep(); + + // Static callbacks + static void staticWrtStatusCallback(std::string tizenId, + WrtErrStatus status, + void* userdata); + static void staticWrtPluginInstallationCallback(WrtErrStatus status, + void* userdata); + static void staticWrtPluginInstallProgressCb(float percent, + const char* description, + void* userdata); + static void staticWrtInstallProgressCallback(float percent, + const char* description, + void* userdata); + + static void staticWrtUninstallProgressCallback(float percent, + const char* description, + void* userdata); + + static void staticWrtInitializeToPreloadCallback(std::string tizenId, + WrtErrStatus status, + void* userdata); + + static void staticWrtInitPreloadStatusCallback(std::string tizenId, + WrtErrStatus status, + void* userdata); + + void installNewPlugins(); + void showErrorMsg(WrtErrStatus status, std::string tizenId, std::string + printMsg); + + void makeStatusOfWrtInit(WrtErrStatus status); + void getRecoveryPackageId(std::string &pkgId); + bool setInitialCSC(std::string cscPath); + + // Private data + std::shared_ptr pkgmgrSignalInterface; + InstallMode m_installMode; + std::string m_packagePath; + std::string m_name; + bool m_initialized; + size_t m_numPluginsToInstall; + size_t m_totalPlugins; + int m_returnStatus; + bool m_sendPkgSig; + bool m_startupPluginInstallation; + + typedef std::list PluginPathList; + boost::optional m_pluginsPaths; +}; +#endif // WRT_INSTALLER_H diff --git a/src_wearable/wrt-installer/wrt_type.h b/src_wearable/wrt-installer/wrt_type.h new file mode 100644 index 0000000..3a5ed67 --- /dev/null +++ b/src_wearable/wrt-installer/wrt_type.h @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file wrt_type.h + * @author jihoon Chung (jihoon.Chung@samsung.com) + * @version 1.0 + * @brief This file contains declarations of wrt api + */ + +/* + * @defgroup wrt_engine_group WebRunTime engine Library + * @ingroup internet_FW + * Functions to APIs to access wrt-engine + */ + +#ifndef WRT_TYPE_H_ +#define WRT_TYPE_H_ + +#include +#include + +#define WRT_DEPRECATED __attribute__((deprecated)) + +typedef enum +{ + /* Generic success */ + WRT_SUCCESS = 0, /*< Success*/ + + /* pkgmgr error */ + WRT_INSTALLER_ERROR_PACKAGE_NOT_FOUND, ///< + WRT_INSTALLER_ERROR_PACKAGE_INVALID, ///< invalid widget package + WRT_INSTALLER_ERROR_PACKAGE_LOWER_VERSION, ///< given version is lower than existing version + WRT_INSTALLER_ERROR_PACKAGE_EXCUTABLE_NOT_FOUND, + + WRT_INSTALLER_ERROR_MANIFEST_NOT_FOUND = 11,///< + WRT_INSTALLER_ERROR_MANIFEST_INVALID, ///< + WRT_INSTALLER_CONFIG_NOT_FOUND, ///< couldn't find config.xml + ///< in package. + WRT_INSTALLER_ERROR_CONFIG_INVALID, ///< invalid config.xml + + WRT_INSTALLER_ERROR_SIGNATURE_NOT_FOUND = 21, ///< signature file not exist. + WRT_INSTALLER_ERROR_SIGNATURE_INVALID, ///< invalid signature file + WRT_INSTALLER_ERROR_SIGNATURE_VERIFICATION_FAILED, ///< failure in verificate signature + WRT_INSTALLER_ERROR_ROOT_CERTIFICATE_NOT_FOUND = 31, ///< couldn't find root certificate. + WRT_INSTALLER_ERROR_CERTIFICATION_INVAID, ///< invalid certification + WRT_INSTALLER_ERROR_CERTIFICATE_CHAIN_VERIFICATION_FAILED, ///< failure in verificate certification chain. + WRT_INSTALLER_ERROR_CERTIFICATE_EXPIRED, ///< expire cerification. + + WRT_INSTALLER_ERROR_INVALID_PRIVILEGE = 41, ///< invalid privilege. + WRT_INSTALLER_ERROR_PRIVILEGE_LEVEL_VIOLATION, + + WRT_INSTALLER_ERROR_MENU_ICON_NOT_FOUND = 51, ///< + + WRT_INSTALLER_ERROR_FATAL_ERROR = 61, ///< failure in db operation or file opertion.. + WRT_INSTALLER_ERROR_OUT_OF_STORAGE, ///< failure in shortage of memory + WRT_INSTALLER_ERROR_OUT_OF_MEMORY, ///< failure in shortage of RAM + WRT_INSTALLER_ERROR_ARGUMENT_INVALID, + + /* wrt-installer error */ + /* 121-140 : reserved for Web installer */ + + /* installation */ + WRT_INSTALLER_ERROR_PACKAGE_ALREADY_INSTALLED = 121, + WRT_INSTALLER_ERROR_ACE_CHECK_FAILED, + WRT_INSTALLER_ERROR_MANIFEST_CREATE_FAILED, ///< + WRT_INSTALLER_ERROR_ENCRYPTION_FAILED, ///< Failure in reousrce encrypttion + WRT_INSTALLER_ERROR_INSTALL_OSP_SERVCIE, ///< Failure in installing osp service + WRT_INSTALLER_ERROR_PLUGIN_INSTALLATION_FAILED, + WRT_INSTALLER_ERROR_UNINSTALLATION_FAILED, + + WRT_INSTALLER_ERROR_UNKNOWN = 140, ///< do not use this error code. + +} WrtErrStatus; + +#endif /* WRT_TYPE_H_ */ diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 0000000..5951524 --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1,20 @@ +# Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @file CMakeLists.txt +# @author Karol Pawlowski (k.pawlowski@samsung.com) +# + + +ADD_SUBDIRECTORY(general) diff --git a/tests/general/AceRegistrationTests.cpp b/tests/general/AceRegistrationTests.cpp new file mode 100644 index 0000000..969c194 --- /dev/null +++ b/tests/general/AceRegistrationTests.cpp @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file AceRegistrationTests.cpp + * @author Dominik Duda (d.duda@samsung.com) + * @version 1.0 + * @brief Tests functions from wrt-installer/src/jobs/widget_install/ace_registration.cpp + */ + +#include +#include +#include +#include +#include +#include +#include + + +using namespace AceApi; +using namespace WrtDB; +using namespace InstallerWrapper; + +RUNNER_TEST_GROUP_INIT(AceRegistration) + +namespace{ + const std::string wgtPath = miscWidgetsStuff + "widgets/widgetUpdateVer100Signed.wgt"; + + std::string tizenId; + DbWidgetHandle wgtHandle; +} + +/* +Name: ace_registration_tests_00 +Description: Install a widget which is needed for further tests. +Expected: The widget should be successfully installed. +*/ +RUNNER_TEST(ace_registration_tests_00) +{ + RUNNER_ASSERT_MSG(install(wgtPath, tizenId) == InstallerWrapper::Success, + "Failed to install widget"); + + wgtHandle = WidgetDAOReadOnly::getHandle(DPL::FromUTF8String(tizenId)); +} + +/* +Name: ace_registration_tests_01 +Description: Tests registration of the widget in ACE database. +Expected: The widget should be successfully registered. +*/ +RUNNER_TEST(ace_registration_tests_01) +{ + bool test1; + ace_return_t test2, test3, test4; + WidgetRegisterInfo regInfo; + WidgetCertificateDataList certificates; + WidgetCertificateData cert1, cert2, cert3; + + regInfo.webAppType.appType = WrtDB::APP_TYPE_TIZENWEBAPP; + regInfo.configInfo.widget_id = DPL::FromUTF8String(tizenId); + regInfo.configInfo.version = DPL::FromUTF8String("1.0"); + regInfo.configInfo.authorName = DPL::FromUTF8String("Author"); + + cert1.owner = WidgetCertificateData::Owner::AUTHOR; + cert1.type = WidgetCertificateData::Type::ROOT; + cert1.chainId = wgtHandle; + cert1.strMD5Fingerprint = ""; + cert1.strSHA1Fingerprint = ""; + cert1.strCommonName = DPL::FromUTF8String(""); + + cert2.owner = WidgetCertificateData::Owner::DISTRIBUTOR; + cert2.type = WidgetCertificateData::Type::ENDENTITY; + cert2.chainId = wgtHandle; + cert2.strMD5Fingerprint = ""; + cert2.strSHA1Fingerprint = ""; + cert2.strCommonName = DPL::FromUTF8String(""); + + cert3.owner = WidgetCertificateData::Owner::UNKNOWN; + cert3.type = static_cast(2); + cert3.chainId = wgtHandle; + cert3.strMD5Fingerprint = ""; + cert3.strSHA1Fingerprint = ""; + cert3.strCommonName = DPL::FromUTF8String(""); + + certificates.push_back(cert1); + certificates.push_back(cert2); + certificates.push_back(cert3); + + test2 = ace_install_initialize(); + wgtHandle = WidgetDAOReadOnly::getHandle(DPL::FromUTF8String(tizenId)); + + //Unregister widget in ACE db in order to test registerAceWidget function + test3 = ace_unregister_widget( + static_cast(wgtHandle)); + test1 = registerAceWidget(wgtHandle, regInfo, certificates); + test4 = ace_install_shutdown(); + + RUNNER_ASSERT_MSG(test1, "Registering widget from the DB failed!"); + RUNNER_ASSERT_MSG(test2 == ACE_OK, "Cannot initialize ACE database!"); + RUNNER_ASSERT_MSG(test2 == ACE_OK, "Cannot unregister widget in ACE database!"); + RUNNER_ASSERT_MSG(test2 == ACE_OK, "Shutting down ACE database failed!"); +} + +/* +Name: ace_registration_tests_02 +Description: Tests registration of the widget which data already are in +the database. +Expected: The widget should be successfully registered. +*/ +RUNNER_TEST(ace_registration_tests_02) +{ + bool test1; + ace_return_t test2, test3, test4; + + test2 = ace_install_initialize(); + + //Unregister widget in ACE db in order to test registerAceWidgetFromDB + //function + test3 = ace_unregister_widget( + static_cast(wgtHandle)); + test1 = registerAceWidgetFromDB(wgtHandle); + test4 = ace_install_shutdown(); + + RUNNER_ASSERT_MSG(test1, "Registering widget from the DB failed!"); + RUNNER_ASSERT_MSG(test2 == ACE_OK, "Cannot initialize ACE database!"); + RUNNER_ASSERT_MSG(test2 == ACE_OK, "Cannot unregister widget in ACE database!"); + RUNNER_ASSERT_MSG(test2 == ACE_OK, "Shutting down ACE database failed!"); +} + +/* +Name: ace_registration_tests_03 +Description: Uninstalls the widget previously installed for tests. +Expected: The widget should be successfully uninstalled. +*/ +RUNNER_TEST(ace_registration_tests_03) +{ + RUNNER_ASSERT_MSG(uninstall(tizenId), "Failed to uninstall widget!"); +} diff --git a/tests/general/BackgroundPageTests.cpp b/tests/general/BackgroundPageTests.cpp new file mode 100644 index 0000000..b996cbe --- /dev/null +++ b/tests/general/BackgroundPageTests.cpp @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file TestCases.cpp + * @author Karol Pawlowski (k.pawlowski@samsung.com) + * @author Tomasz Iwanek (t.iwanek@samsung.com) + * @version 1.0 + * @brief Background page installation test's bodies + */ + +#include +#include +#include + +using namespace InstallerWrapper; + +//////////////////////////////////////////////////////////////////////////////// + +RUNNER_TEST_GROUP_INIT(BackgroundPage) + +/* +Name: widgetWithBackgroundPage +Description: Tests if widget with background page is installed correctly +Expected: widget should be installed correctly +*/ +RUNNER_TEST(widgetWithBackgroundPage) +{ + std::string tizenId; + RUNNER_ASSERT(install(miscWidgetsStuff + "widgets/bg-00-with_bg.wgt", + tizenId) == InstallerWrapper::Success); + uninstall(tizenId); +} + +/* +Name: missingBackgroundFile +Description: Tests if widget with declared in conifg background page + but missing background file will be installed correctly. +Expected: widget should NOT be installed +*/ +RUNNER_TEST(missingBackgroundFile) +{ + std::string tizenId; + if(install(miscWidgetsStuff + "widgets/bg-01-missing_file.wgt", + tizenId) == InstallerWrapper::Success) { + uninstall(tizenId); + RUNNER_ASSERT_MSG(false, "Invalid widget package installed"); + } +} + +/* +Name: widgetWithoutBackgroundPage +Description: Complementary test to check if normal widget\ + without background page is successfully installed +Expected: widget should be installed +*/ +RUNNER_TEST(widgetWithoutBackgroundPage) +{ + std::string tizenId; + RUNNER_ASSERT(install(miscWidgetsStuff + "widgets/bg-02-without_bg.wgt", + tizenId) == InstallerWrapper::Success); + uninstall(tizenId); +} diff --git a/tests/general/CMakeLists.txt b/tests/general/CMakeLists.txt new file mode 100644 index 0000000..05a4161 --- /dev/null +++ b/tests/general/CMakeLists.txt @@ -0,0 +1,181 @@ +# Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# @file CMakeLists.txt +# @author Karol Pawlowski (k.pawlowski@samsung.com) +# + +PKG_CHECK_MODULES(COMMON_LIB_PKGS + dbus-1 + libpcrecpp + dpl-efl + dpl-test-efl + dpl-utils-efl + dpl-wrt-dao-ro + dpl-event-efl + cert-svc-vcore + xmlsec1 + libiri + REQUIRED + ) + +pkg_search_module(dpl REQUIRED dpl-efl) +pkg_search_module(dpl-test REQUIRED dpl-test-efl) + +SET(WRT_TEST_LIBRARY "wrt-tests-libs") + +include_directories( + ${dpl_INCLUDE_DIRS} + ${dpl-test_INCLUDE_DIRS} + ${ace-client_INCLUDE_DIRS} +) + +SET(COMMON_INCLUDES "${CMAKE_CURRENT_SOURCE_DIR}") + +SET_PROPERTY(GLOBAL APPEND PROPERTY COMMON_TESTS_LIBRARY ${WRT_TEST_LIBRARY}) + +SET_PROPERTY(GLOBAL APPEND PROPERTY TESTS_INCLUDE_DIRS ${COMMON_LIB_PKGS_INCLUDE_DIRS}) + +SET_PROPERTY(GLOBAL APPEND PROPERTY TESTS_LIBRARY_DIRS ${COMMON_LIB_PKGS_LIBRARY_DIRS}) + +SET_PROPERTY(GLOBAL APPEND PROPERTY TESTS_LIBRARIES ${COMMON_LIB_PKGS_LIBRARIES}) + +SET(WRT_DETAIL_SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/InstallerWrapper.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/ManifestFile.cpp +) + +INCLUDE_DIRECTORIES(${COMMON_INCLUDES}) +INCLUDE_DIRECTORIES(${COMMON_LIB_PKGS_INCLUDE_DIRS}) +INCLUDE_DIRECTORIES(SYSTEM ${SYS_INSTALLER_STATIC_DEP_INCLUDE_DIRS}) + +ADD_LIBRARY(${WRT_TEST_LIBRARY} STATIC ${WRT_DETAIL_SOURCES}) + + +SET(INSTALLER_TESTS_TARGET "wrt-installer-tests-general") + +PKG_CHECK_MODULES(INSTALLER_TESTS_DEPS + wrt-commons-i18n-dao-ro + REQUIRED) + +SET(INSTALLER_TESTS_SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/TestInit.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/ManifestTests.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/BackgroundPageTests.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/NPluginsInstallTests.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/ParsingAccountTests.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/ParsingAllowNavigationTests.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/ParsingAppWidgetTests.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/ParsingCategoryTests.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/ParsingContentTests.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/ParsingCspTests.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/ParsingMetadataTests.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/ParsingTizenAppcontrolTests.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/ParsingTizenPrivilegeTests.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/ParsingSplashImgTests.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/WidgetUpdateTests.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/PluginsInstallation.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/LanguageSubtagRstTreeTests.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/WidgetInstallManifestTests.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/WidgetLocationTests.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/AceRegistrationTests.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/ParserRunnerTests.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/TaskConfigurationTests.cpp + ${CMAKE_SOURCE_DIR}/src/wrt-installer/language_subtag_rst_tree.cpp + ${CMAKE_SOURCE_DIR}/src/wrt-installer/installer_callbacks_translate.cpp +) + +SET(INSTALLER_TESTS_INCLUDE_DIRS + ${INSTALLER_TESTS_DEPS_INCLUDE_DIRS} + ${CMAKE_SOURCE_DIR}/src/wrt-installer + ${CMAKE_SOURCE_DIR}/src/configuration_parser + ${CMAKE_SOURCE_DIR}/src/commons + ${CMAKE_SOURCE_DIR}/src/jobs + ${CMAKE_SOURCE_DIR}/src/jobs/widget_install + ${CMAKE_SOURCE_DIR}/src + ${CMAKE_SOURCE_DIR}/src/misc + ${CMAKE_SOURCE_DIR}/src/pkg-manager +) + +# Functions used to build test targets (proper sources, includes, libs are +# added automatically) +FUNCTION(WRT_TEST_BUILD TARGET_NAME) + # get include dirs global property + GET_PROPERTY(INCLUDE_DIRS GLOBAL PROPERTY TESTS_INCLUDE_DIRS) + GET_PROPERTY(TEST_INCLUDE_DIRS GLOBAL PROPERTY ${TARGET_NAME}_INCLUDE_DIRS) + INCLUDE_DIRECTORIES( + ${INCLUDE_DIRS} + ${TEST_INCLUDE_DIRS} + ) + + # get library dirs global property + GET_PROPERTY(LIBRARY_DIRS GLOBAL PROPERTY TESTS_LIBRARY_DIRS) + GET_PROPERTY(TEST_LIBRARY_DIRS GLOBAL PROPERTY ${TARGET_NAME}_LIBRARY_DIRS) + LINK_DIRECTORIES( + ${LIBRARY_DIRS} + ${TEST_LIBRARY_DIRS} + ) + + SET(SOURCES "${ARGN}") + ADD_EXECUTABLE("${TARGET_NAME}" ${SOURCES}) + + # get link libraries global property + GET_PROPERTY(LINK_LIBRARIES GLOBAL PROPERTY TESTS_LIBRARIES) + GET_PROPERTY(TEST_LIBRARIES GLOBAL PROPERTY ${TARGET_NAME}_LIBRARIES) + TARGET_LINK_LIBRARIES("${TARGET_NAME}" + ${LINK_LIBRARIES} + ${TEST_LIBRARIES} + ) +ENDFUNCTION(WRT_TEST_BUILD) + +FUNCTION(WRT_TEST_INSTALL) + SET_TARGET_PROPERTIES(${ARGV} PROPERTIES + BUILD_WITH_INSTALL_RPATH ON + INSTALL_RPATH_USE_LINK_PATH ON + ) + INSTALL(TARGETS ${ARGV} + DESTINATION bin + PERMISSIONS OWNER_READ + OWNER_WRITE + OWNER_EXECUTE + GROUP_READ + GROUP_EXECUTE + WORLD_READ + WORLD_EXECUTE + ) +ENDFUNCTION(WRT_TEST_INSTALL) + +FUNCTION(WRT_TEST_INCLUDE_DIRS TARGET_NAME) + SET_PROPERTY(GLOBAL APPEND PROPERTY ${TARGET_NAME}_INCLUDE_DIRS ${ARGN}) +ENDFUNCTION(WRT_TEST_INCLUDE_DIRS) + +WRT_TEST_INCLUDE_DIRS(${INSTALLER_TESTS_TARGET} ${INSTALLER_TESTS_INCLUDE_DIRS}) +WRT_TEST_BUILD(${INSTALLER_TESTS_TARGET} ${INSTALLER_TESTS_SOURCES}) +WRT_TEST_INSTALL(${INSTALLER_TESTS_TARGET}) +target_link_libraries(${INSTALLER_TESTS_TARGET} + ${dpl_LIBRARIES} + ${dpl-test_LIBRARIES} + ${WRT_TEST_LIBRARY} + ${TARGET_CORE_MODULE_LIB} + ${COMMON_LIB_PKGS_LIBRARIES} + ${INSTALLER_TESTS_DEPS_LIBRARIES} + ${TARGET_INSTALLER_STATIC} +) + +#widgets +FILE(GLOB files "${CMAKE_CURRENT_SOURCE_DIR}/widgets/*.wgt") +INSTALL(FILES ${files} "${CMAKE_CURRENT_SOURCE_DIR}/widgets/widgetInDir.tar" DESTINATION /opt/share/widget/tests/installer/widgets/) + +FILE(GLOB files_conf "${CMAKE_CURRENT_SOURCE_DIR}/configs/*.xml") +INSTALL(FILES ${files_conf} DESTINATION /opt/share/widget/tests/installer/configs/) diff --git a/tests/general/InstallerWrapper.cpp b/tests/general/InstallerWrapper.cpp new file mode 100644 index 0000000..de98a3f --- /dev/null +++ b/tests/general/InstallerWrapper.cpp @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "InstallerWrapper.h" + +#include + +#include + +namespace +{ + +const std::string params = "DPL_USE_OLD_STYLE_LOGS=0 " + "DPL_USE_OLD_STYLE_PEDANTIC_LOGS=0 WRT_TEST_MODE=1 "; +const std::string installCmd = params + "wrt-installer -i "; +const std::string uninstallCmd = params + "wrt-installer -un "; +const std::string redirection = " 2>&1"; +const std::string INSTALLER_MESSAGE_ID_LINE = + "## wrt-installer : %s installation was successful.\n"; +const std::string INSTALLER_MESSAGE_ID_LINE_FAIL = + "## wrt-installer : %s installation has failed - package already installed"; +const std::string INSTALLER_MESSSGE_START = "## wrt-installer : "; + +std::string getAndCutInstallerLogLine(std::string &src) +{ + size_t startIndex = src.find(INSTALLER_MESSSGE_START); + if (startIndex == std::string::npos) + { + _W("Installer message can not be found"); + return std::string(); + } + size_t newLineIndex = src.find("\n", startIndex); + std::string line = src.substr(startIndex, newLineIndex - startIndex + 1); + src.erase(0, newLineIndex + 1); + return line; +} + +} + +namespace InstallerWrapper +{ + +InstallResult install( + const std::string& path, + std::string& tizenId, + const std::string& user) +{ + std::string msg; + + auto cmd = installCmd + path + redirection; + if(user.length()) //if other user should be used + { + cmd = "su " + user + " -c '" + cmd + "'"; + } + auto filehandle = popen(cmd.c_str(), "r"); + if (!filehandle) {; + return OtherError; + } + + char buffer[1024] = ""; + while ( fread_unlocked(buffer, sizeof(char), + sizeof(buffer)/sizeof(char), filehandle) > 0 ) + { + msg += buffer; + } + _D("%s", msg.c_str()); + auto err = pclose(filehandle); + if (!WIFEXITED(err)) { + return OtherError; + } + + char* id = NULL; + std::string line; + + if (0 != WEXITSTATUS(err)) { + while ((line = getAndCutInstallerLogLine(msg)) != "") + { + if(line.find("failed") != std::string::npos) + { + id = new char[line.length()]; + int nr = sscanf(line.c_str(), INSTALLER_MESSAGE_ID_LINE_FAIL.c_str(), id); + if (1 != nr) + { + _W("Can not read widget ID from message: %s", line.c_str()); + delete[] id; + return OtherError; + } + tizenId = id; + delete[] id; + } + } + + if (1 == WEXITSTATUS(err)) { + return WrongWidgetPackage; + } + return OtherError; + } + + while ((line = getAndCutInstallerLogLine(msg)) != "") + { + if (line.find("successful") != std::string::npos) + { + id = new char[line.length()]; + int nr = sscanf(line.c_str(), INSTALLER_MESSAGE_ID_LINE.c_str(), id); + + if (1 != nr) + { + _W("Can not read widget ID from message: %s", line.c_str()); + delete[] id; + return OtherError; + } + tizenId = id; + delete[] id; + if (tizenId != "plugin") + { + return Success; + } + } + } + + return OtherError; +} + +bool uninstall(const std::string& tizenId) +{ + std::string cmd = uninstallCmd + tizenId + " > /dev/null 2>/dev/null"; + _D("executing: %s", cmd.c_str()); + return (system(cmd.c_str()) == EXIT_SUCCESS); +} + +bool sigintWrtClients() +{ + return (system("pkill -2 wrt-client") == 0); +} + +} + diff --git a/tests/general/InstallerWrapper.h b/tests/general/InstallerWrapper.h new file mode 100644 index 0000000..404a3e8 --- /dev/null +++ b/tests/general/InstallerWrapper.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef WRT_INSTALLER_TESTS_GENERAL_INSTALLER_WRAPPER_H +#define WRT_INSTALLER_TESTS_GENERAL_INSTALLER_WRAPPER_H + +#include + +namespace InstallerWrapper +{ + +typedef int InstallResult; +const InstallResult WrongWidgetPackage = -2; +const InstallResult OtherError = -1; +const InstallResult Success = 0; + +const std::string miscWidgetsStuff = "/opt/share/widget/tests/installer/"; + +struct Result { + bool m_exc; + bool m_exd; + bool m_exs; + std::string message; + Result(bool exc = false, bool exd = false, bool exs = false) + : m_exc(exc), m_exd(exd), m_exs(exs) {} +}; + +InstallResult install( + const std::string& path, + std::string& tizenId, + const std::string& user = ""); +bool uninstall(const std::string& tizenId); +/** + * @brief killWrtClients kills processes that matches 'wrt-client' + * @return True if any client was killed + */ +bool sigintWrtClients(); + +} + +#endif//WRT_INSTALLER_TESTS_GENERAL_INSTALLER_WRAPPER_H diff --git a/tests/general/LanguageSubtagRstTreeTests.cpp b/tests/general/LanguageSubtagRstTreeTests.cpp new file mode 100644 index 0000000..bd05f87 --- /dev/null +++ b/tests/general/LanguageSubtagRstTreeTests.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file LanguageSubtagRstTreeTests.cpp + * @author Zbigniew Kostrzewa (z.kostrzewa@samsung.com) + * @version 1.0 + * @brief Language tags tests + */ + +#include +#include + +namespace { +const char LANGUAGE_TAG_VALID[] = "en-us"; +const char LANGUAGE_TAG_INVALID[] = "invalid0"; +} + +//////////////////////////////////////////////////////////////////////////////// + +RUNNER_TEST_GROUP_INIT(LanguageSubtagRstTree) + +/* +Name: ValidateLanguageTag_Valid +Description: tests result returned for valid language tag +Expected: value true should be returned +*/ +RUNNER_TEST(ValidateLanguageTag_Valid) +{ + RUNNER_ASSERT(LanguageSubtagRstTreeSingleton::Instance(). + ValidateLanguageTag(LANGUAGE_TAG_VALID)); +} + +/* +Name: ValidateLanguageTag_Invalid +Description: tests result returned for invalid language tag +Expected: value false should be returned +*/ +RUNNER_TEST(ValidateLanguageTag_Invalid) +{ + RUNNER_ASSERT(!LanguageSubtagRstTreeSingleton::Instance(). + ValidateLanguageTag(LANGUAGE_TAG_INVALID)); +} diff --git a/tests/general/ManifestFile.cpp b/tests/general/ManifestFile.cpp new file mode 100644 index 0000000..2206c2a --- /dev/null +++ b/tests/general/ManifestFile.cpp @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file ManifestFile.cpp + * @author Tomasz Iwanek (t.iwanek@samsung.com) + * @brief Manifest file reading + */ + +#include + +#include +#include + +#include + +//TODO: This file reads manifest file. This functionality is familiar with writing +// in wrt-installer but reading ws not necessary there. +// Maybe it should be changed in some way. + +ManifestFile::ManifestFile(const std::string & file) : filename(file) +{ + xmlXPathInit(); + parse(); +} + +ManifestFile::~ManifestFile() +{ + xmlXPathFreeContext(xpathCtx); + xmlFreeDoc(doc); +} + +void ManifestFile::parse() +{ + doc = xmlReadFile(filename.c_str(), NULL, 0); + if (doc == NULL) + { + ThrowMsg(ManifestParseError,"File Problem"); + } + else + { + //context + xpathCtx = xmlXPathNewContext(doc); + if(xpathCtx == NULL) + { + ThrowMsg(ManifestParseError,"Error: unable to create new XPath context\n"); + } + xpathCtx->node = xmlDocGetRootElement(doc); + + if(xmlXPathRegisterNs(xpathCtx, BAD_CAST "p", BAD_CAST "http://tizen.org/ns/packages") != 0) + { + ThrowMsg(ManifestParseError,"Error: unable to register namespace\n"); + } + } +} + +std::string ManifestFile::getValueByXpath(const std::string & path) const +{ + std::string result; + xmlXPathObjectPtr xpathObject; + //get requested node's values + xpathObject = xmlXPathEvalExpression(BAD_CAST path.c_str(), xpathCtx); + if(xpathObject == NULL) + { + ThrowMsg(ManifestParseError,"XPath evaluation failure: " << path); + } + xmlNodeSetPtr nodes = xpathObject->nodesetval; + int size = (nodes) ? nodes->nodeNr : 0; + if(size != 1) + { + ThrowMsg(ManifestParseError,"Xpath does not point 1 element but " << size + << " for xpath: " << path); + } + else + { + if(nodes->nodeTab[0]->type == XML_ELEMENT_NODE) + { + xmlNodePtr cur = nodes->nodeTab[0]; + xmlChar * value = xmlNodeGetContent(cur); + result = std::string(reinterpret_cast(value)); //this cast should be safe... + xmlFree(value); + } + else if(nodes->nodeTab[0]->type == XML_ATTRIBUTE_NODE) + { + xmlNodePtr cur = nodes->nodeTab[0]; + xmlChar * value = xmlNodeGetContent(cur); + result = std::string(reinterpret_cast(value)); + xmlFree(value); + } + } + //Cleanup of XPath data + xmlXPathFreeObject(xpathObject); + return result; +} diff --git a/tests/general/ManifestFile.h b/tests/general/ManifestFile.h new file mode 100644 index 0000000..ccb6a7b --- /dev/null +++ b/tests/general/ManifestFile.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file ManifestFile.h + * @author Tomasz Iwanek (t.iwanek@samsung.com) + * @brief Manifest file reading + */ + +#ifndef WRT_INSTALLER_TESTS_GENERAL_MANIFESTFILE_H +#define WRT_INSTALLER_TESTS_GENERAL_MANIFESTFILE_H + +#include + +#include +#include + +#include + +/** + * @brief The ManifestFile class which serialize xml file to tree + */ +class ManifestFile +{ +public: + DECLARE_EXCEPTION_TYPE(DPL::Exception,Base) + DECLARE_EXCEPTION_TYPE(Base,ManifestParseError) + + ManifestFile(const std::string & file); + ~ManifestFile(); + + std::string getValueByXpath(const std::string & path) const; +private: + void parse(); + + std::string filename; + xmlDocPtr doc; + xmlXPathContextPtr xpathCtx; +}; + + +#endif //WRT_INSTALLER_TESTS_GENERAL_MANIFESTFILE_H diff --git a/tests/general/ManifestTests.cpp b/tests/general/ManifestTests.cpp new file mode 100644 index 0000000..4e316da --- /dev/null +++ b/tests/general/ManifestTests.cpp @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file TestCases.cpp + * @author Karol Pawlowski (k.pawlowski@samsung.com) + * @author Tomasz Iwanek (t.iwanek@samsung.com) + * @version 1.0 + * @brief Manifest installation test's bodies + */ + +#include +#include +#include +#include +#include +#include +#include + +using namespace InstallerWrapper; + +//////////////////////////////////////////////////////////////////////////////// + +RUNNER_TEST_GROUP_INIT(Manifest) + +/* +Name: creatingManifestFile +Description: Creation of manifest file by wrt-installer test +Expected: file should be created and installed by wrt-installer. Content should + match expected values +*/ +RUNNER_TEST(creatingManifestFile) +{ + std::string manifestPath = "/opt/share/packages/"; + /* This widget removal should stay here in case previous test run failed + * (so widget has not been uninstalled) */ + std::string tizenId; + + if(install(miscWidgetsStuff + "widgets/manifest.wgt", tizenId) + != InstallerWrapper::Success) + { + uninstall(tizenId); + RUNNER_ASSERT(install(miscWidgetsStuff + "widgets/manifest.wgt", tizenId) + == InstallerWrapper::Success); + } + + RUNNER_ASSERT(WrtUtilFileExists(manifestPath.append(tizenId.substr(0,10)).append(".xml"))); + ManifestFile mf(manifestPath); + + Try + { + _D("Package %s", mf.getValueByXpath("/p:manifest/@package").c_str()); + RUNNER_ASSERT(mf.getValueByXpath("/p:manifest/@package") + == tizenId.substr(0,10)); + _D("type %s", mf.getValueByXpath("/p:manifest/@type").c_str()); + RUNNER_ASSERT(mf.getValueByXpath("/p:manifest/@type") + == "wgt"); + _D("version %s", mf.getValueByXpath("/p:manifest/@version").c_str()); + RUNNER_ASSERT(mf.getValueByXpath("/p:manifest/@version") + == "1.0"); + _D("label %s", mf.getValueByXpath("/p:manifest/p:label").c_str()); + RUNNER_ASSERT(mf.getValueByXpath("/p:manifest/p:label") + == "Manifest Example"); + + _D("email %s", mf.getValueByXpath("/p:manifest/p:author/@email").c_str()); + RUNNER_ASSERT(mf.getValueByXpath("/p:manifest/p:author/@email") + == "manifest@misc.test.create.desktop.com"); + _D("href %s", mf.getValueByXpath("/p:manifest/p:author/@href").c_str()); + RUNNER_ASSERT(mf.getValueByXpath("/p:manifest/p:author/@href") + == "http://misc.test.create.desktop.com"); + _D("author %s", mf.getValueByXpath("/p:manifest/p:author").c_str()); + RUNNER_ASSERT(mf.getValueByXpath("/p:manifest/p:author") + == "Manifest"); + + _D("appid %s", mf.getValueByXpath("/p:manifest/p:ui-application/@appid").c_str()); + RUNNER_ASSERT(mf.getValueByXpath("/p:manifest/p:ui-application/@appid") + == tizenId); + _D("type %s", mf.getValueByXpath("/p:manifest/p:ui-application/@type").c_str()); + RUNNER_ASSERT(mf.getValueByXpath("/p:manifest/p:ui-application/@type") + == "webapp"); + _D("extraid %s", mf.getValueByXpath("/p:manifest/p:ui-application/@extraid").c_str()); + RUNNER_ASSERT(mf.getValueByXpath("/p:manifest/p:ui-application/@extraid") + == "http://test.samsung.com/widget/manifestTest"); + _D("icon %s", mf.getValueByXpath("/p:manifest/p:ui-application/p:icon").c_str()); + RUNNER_ASSERT(mf.getValueByXpath("/p:manifest/p:ui-application/p:icon") + == (std::string(WrtDB::GlobalConfig::GetUserInstalledWidgetPath()) + "/" + tizenId.substr(0,10) + WrtDB::GlobalConfig::GetWidgetSharedPath() + WrtDB::GlobalConfig::GetWidgetResPath() + "/" + tizenId + ".png")); + + RUNNER_ASSERT(mf.getValueByXpath("/p:manifest/p:ui-application/p:label[not(@xml:lang)]") + == "Manifest Example"); + RUNNER_ASSERT(mf.getValueByXpath("/p:manifest/p:ui-application/p:label[@xml:lang='de-de']") + == "Manifest Beispiel"); + RUNNER_ASSERT(mf.getValueByXpath("/p:manifest/p:ui-application/p:label[@xml:lang='en-us']") + == "Manifest Example"); + RUNNER_ASSERT(mf.getValueByXpath("/p:manifest/p:ui-application/p:label[@xml:lang='pl']") + == "Przykład Manifest"); + RUNNER_ASSERT(mf.getValueByXpath("/p:manifest/p:ui-application/p:label[@xml:lang='pt-pt']") + == "Exemplo manifesto"); + } + Catch(ManifestFile::ManifestParseError) + { + RUNNER_ASSERT_MSG(false,DPL::Exception::KnownExceptionToString(_rethrown_exception)); + } + /* If test finished sucessfully than uninstall test widget */ + uninstall(tizenId); +} diff --git a/tests/general/NPluginsInstallTests.cpp b/tests/general/NPluginsInstallTests.cpp new file mode 100644 index 0000000..ac141d8 --- /dev/null +++ b/tests/general/NPluginsInstallTests.cpp @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file TestCases.cpp + * @author Karol Pawlowski (k.pawlowski@samsung.com) + * @author Tomasz Iwanek (t.iwanek@samsung.com) + * @version 1.0 + * @brief NPlugins installation test's bodies + */ + +#include +#include +#include + +using namespace InstallerWrapper; + +//////////////////////////////////////////////////////////////////////////////// + +RUNNER_TEST_GROUP_INIT(NPluginsInstall) + +/* +Name: pluginFilesAdded +Description: Tests installation of plugins attached to widget +Expected: widget should be succesfully installed +*/ +RUNNER_TEST(pluginFilesAdded) +{ + std::string tizenId; + RUNNER_ASSERT(install(miscWidgetsStuff + + "widgets/inst_nplug_1.wgt", tizenId) == InstallerWrapper::Success); + uninstall(tizenId); +} + +/* +Name: pluginFileAndOtherFile +Description: Tests installation with plugins directory and data files +Expected: widget should be installed +*/ +RUNNER_TEST(pluginFileAndOtherFile) +{ + std::string tizenId; + RUNNER_ASSERT(install(miscWidgetsStuff + + "widgets/inst_nplug_3.wgt", tizenId) == InstallerWrapper::Success); + uninstall(tizenId); +} diff --git a/tests/general/ParserRunnerTests.cpp b/tests/general/ParserRunnerTests.cpp new file mode 100644 index 0000000..e87d90f --- /dev/null +++ b/tests/general/ParserRunnerTests.cpp @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file ParserRunnerTests.cpp + * @author Adrian Szafranek (a.szafranek@samsung.com) + * @version 1.0 + * @brief Perform ParserRunner test's. + */ + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +RUNNER_TEST_GROUP_INIT(ParserRunner) + +using namespace DPL::Utils; + +namespace { +const std::string rootTest = "/tmp/"; +const std::string schemaFile = "/usr/etc/wrt-installer/widgets.xsd"; +const std::string configFile = "/usr/lib/wrt-plugins/tizen-content/config.xml"; +const std::string installConfigFile = "/opt/share/widget/tests/installer/configs/InstallConfig.xml"; +} + +class StreamRedirector +{ + public: + StreamRedirector(FILE* src, std::string dest) + : source(src), file_dest(dest) + { + fd = dup(fileno(source)); + if ((fd < 0) || (freopen(file_dest.c_str(), "w", source) == NULL)) + { + _D("Error catching stream."); + } + } + ~StreamRedirector() + { + if (TEMP_FAILURE_RETRY(fflush(source)) == 0) + { + if (dup2(fd, fileno(source)) >= 0) + { + close(fd); + clearerr(source); + } + else + { + _D("Error returning stream."); + } + } + else + { + _D("Error returning stream."); + } + } + + private: + FILE* source; + std::string file_dest; + int fd; +}; + + +/* +Name: parserRunner01 +Description: Tests validation and parsing functionality. +Test performed for proper files existing in system, wrong files or empty parameters. +*/ +RUNNER_TEST(parserRunner01) +{ + ParserRunner parser; + + std::unique_ptr sd(new StreamRedirector(stderr, "/dev/null")); + + + if (Path(installConfigFile).Exists() && Path(schemaFile).Exists()) { + RUNNER_ASSERT(parser.Validate(installConfigFile, schemaFile) == true); + } + + if (Path(configFile).Exists() && Path(schemaFile).Exists()) { + RUNNER_ASSERT(parser.Validate(configFile, schemaFile) == false); + } + + RUNNER_ASSERT(parser.Validate("", "") == false); +} + +/* +Name: parserRunner02 +Description: Tests validation and parsing functionality. +Test performed for wrong 'xml', empty 'xsd' file and wrong 'xml', non empty 'xsd' file. +*/ +RUNNER_TEST(parserRunner02) +{ + ParserRunner parser; + + std::unique_ptr sd(new StreamRedirector(stderr, "/dev/null")); + + + Path pathF1 = Path(rootTest + "testFile1.xml"); + if (!pathF1.Exists()) { + MakeEmptyFile(pathF1); + + DPL_SCOPE_EXIT(&pathF1) { TryRemove(pathF1); }; + + std::ofstream ofs1; + ofs1.open(pathF1.Fullpath(), std::ofstream::out); + if (!ofs1) { + RUNNER_ASSERT_MSG(false, "Error creating file"); + } + ofs1 << "wrongContent"; + ofs1.close(); + + RUNNER_ASSERT(parser.Validate(pathF1.Fullpath(), "") == false); + if (Path(schemaFile).Exists()) { + RUNNER_ASSERT(parser.Validate(pathF1.Fullpath(), schemaFile) == false); + } + } +} + +/* +Name: parserRunner03 +Description: Tests validation and parsing functionality. +Test performed for empty 'xml', wrong 'xsd' file and non empty 'xml', wrong 'xsd' file. +*/ +RUNNER_TEST(parserRunner03) +{ + ParserRunner parser; + + std::unique_ptr sd(new StreamRedirector(stderr, "/dev/null")); + + + Path pathF2 = Path(rootTest + "testFile2.xsd"); + if (!pathF2.Exists()) { + MakeEmptyFile(pathF2); + + DPL_SCOPE_EXIT(&pathF2) { TryRemove(pathF2); }; + + std::ofstream ofs2; + ofs2.open(pathF2.Fullpath(), std::ofstream::out); + if (!ofs2) { + RUNNER_ASSERT_MSG(false, "Error creating file"); + } + ofs2 << ""; + ofs2.close(); + + RUNNER_ASSERT(parser.Validate("", pathF2.Fullpath()) == false); + if (Path(configFile).Exists()) { + RUNNER_ASSERT(parser.Validate(configFile, pathF2.Fullpath()) == false); + } + } +} diff --git a/tests/general/ParsingAccountTests.cpp b/tests/general/ParsingAccountTests.cpp new file mode 100644 index 0000000..f19e52b --- /dev/null +++ b/tests/general/ParsingAccountTests.cpp @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file ParsingAccountTests.cpp + * @author Slawomir Pajak (s.pajak@partner.samsung.com) + * @version 1.0 + * @brief Account element installation tests + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +using namespace InstallerWrapper; + +//////////////////////////////////////////////////////////////////////////////// + +RUNNER_TEST_GROUP_INIT(ParsingAccount) + +/* +Name: InstallWidgetWithAccount +Description: Tests if widget with account is installed correctly +Expected: widget should be installed correctly and account information should be present in manifest file +*/ +RUNNER_TEST(InstallWidgetWithAccount) +{ + std::string tizenId; + std::string manifestPath = "/opt/share/packages/"; + RUNNER_ASSERT(install(miscWidgetsStuff + "widgets/account.wgt", tizenId) == InstallerWrapper::Success); + + RUNNER_ASSERT(WrtUtilFileExists(manifestPath.append(tizenId.substr(0, 10)).append(".xml"))); + ManifestFile mf(manifestPath); + WrtDB::WidgetDAOReadOnly dao(DPL::FromASCIIString(tizenId)); + + RUNNER_ASSERT(mf.getValueByXpath("/p:manifest/p:account/p:account-provider/@multiple-accounts-support") == "true"); + RUNNER_ASSERT(mf.getValueByXpath("/p:manifest/p:account/p:account-provider/p:icon[1]/@section") == "account"); + std::string iconPath = DPL::ToUTF8String(*dao.getWidgetInstalledPath()) + WrtDB::GlobalConfig::GetWidgetSharedPath() + + WrtDB::GlobalConfig::GetWidgetResPath() + "/"; + RUNNER_ASSERT(mf.getValueByXpath("/p:manifest/p:account/p:account-provider/p:icon[1]") == iconPath + "icon1.png"); + RUNNER_ASSERT(mf.getValueByXpath("/p:manifest/p:account/p:account-provider/p:icon[2]/@section") == "account-small"); + RUNNER_ASSERT(mf.getValueByXpath("/p:manifest/p:account/p:account-provider/p:icon[2]") == iconPath + "icon2.png"); + RUNNER_ASSERT(mf.getValueByXpath("/p:manifest/p:account/p:account-provider/p:label[1]") == "Name1"); + RUNNER_ASSERT(mf.getValueByXpath("/p:manifest/p:account/p:account-provider/p:label[2]/@xml:lang") == "en-US"); + RUNNER_ASSERT(mf.getValueByXpath("/p:manifest/p:account/p:account-provider/p:label[2]") == "Name2"); + RUNNER_ASSERT(mf.getValueByXpath("/p:manifest/p:account/p:account-provider/p:capability[1]") == "http://tizen.org/account/capability/contact"); + RUNNER_ASSERT(mf.getValueByXpath("/p:manifest/p:account/p:account-provider/p:capability[2]") == "http://tizen.org/account/capability/calendar"); + uninstall(tizenId); +} diff --git a/tests/general/ParsingAllowNavigationTests.cpp b/tests/general/ParsingAllowNavigationTests.cpp new file mode 100644 index 0000000..f5e219c --- /dev/null +++ b/tests/general/ParsingAllowNavigationTests.cpp @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file ParsingAllowNavigationTests.cpp + * @author Slawomir Pajak (s.pajak@partner.samsung.com) + * @version 1.0 + * @brief allow-navigation element installation tests + */ + +#include +#include +#include +#include + +#include +#include +#include + +using namespace InstallerWrapper; + +namespace{ + +struct AllowNavigationComparator { + AllowNavigationComparator(const DPL::String & scheme, const DPL::String& host) : + m_scheme(scheme), m_host(host){} + const DPL::String m_scheme; + const DPL::String m_host; + bool operator()(const WrtDB::ConfigParserData::AllowNavigationInfo& navs) const + { + return navs.m_host == m_host && navs.m_scheme == m_scheme; + } + bool operator()(const WrtDB::WidgetAllowNavigationInfo& navs) const + { + return navs.host == m_host && navs.scheme == m_scheme; + } +}; + +} + + + +//////////////////////////////////////////////////////////////////////////////// + +RUNNER_TEST_GROUP_INIT(ParsingAllowNavigation) + +/* +Name: InstallWidgetWithAllowNavigation +Description: Tests if widget with allow-navigation is installed correctly +Expected: widget should be installed correctly and allowNavigation info should be stored in database +*/ +RUNNER_TEST(InstallWidgetWithAllowNavigation) +{ + std::string tizenId; + RUNNER_ASSERT(install(miscWidgetsStuff + "widgets/allowNavigation.wgt", tizenId) == InstallerWrapper::Success); + + WrtDB::WidgetDAOReadOnly dao(DPL::FromASCIIString(tizenId)); + WrtDB::WidgetAllowNavigationInfoList allowNavigationList; + dao.getWidgetAllowNavigationInfo(allowNavigationList); + + uninstall(tizenId); + + RUNNER_ASSERT(allowNavigationList.size() == 4); + RUNNER_ASSERT(1 == std::count_if(allowNavigationList.begin(), allowNavigationList.end(), + AllowNavigationComparator(L"http",L"test2.org"))); + RUNNER_ASSERT(1 == std::count_if(allowNavigationList.begin(), allowNavigationList.end(), + AllowNavigationComparator(L"*",L"test3.org"))); + RUNNER_ASSERT(1 == std::count_if(allowNavigationList.begin(), allowNavigationList.end(), + AllowNavigationComparator(L"*",L"*.test4.org"))); + RUNNER_ASSERT(1 == std::count_if(allowNavigationList.begin(), allowNavigationList.end(), + AllowNavigationComparator(L"*",L"*"))); +} + + +/* +Name: NoAllowNavigation +Description: Tests parsing configuration file without allow-navigation element +Expected: Element should be parsed correctly. +*/ +RUNNER_TEST(NoAllowNavigation) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + parser.Parse(miscWidgetsStuff + "configs/NoAllowNavigation.xml", + ElementParserPtr( + new RootParser(widgetConfig, + L"widget"))); + + RUNNER_ASSERT(0 == widgetConfig.allowNavigationInfoList.size()); +} + +/* +Name: AllowNavigationEmpty +Description: Tests parsing configuration file with empty allow-navigation element +Expected: Element should be parsed correctly. +*/ +RUNNER_TEST(AllowNavigationEmpty) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + parser.Parse(miscWidgetsStuff + "configs/AllowNavigationEmpty.xml", + ElementParserPtr( + new RootParser(widgetConfig, + L"widget"))); + + RUNNER_ASSERT(0 == widgetConfig.allowNavigationInfoList.size()); +} + +/* +Name: MultipleAllowNavigation +Description: Tests parsing configuration file with multiple allow-navigation element +Expected: Element should be parsed correctly. Only values from first element should be stored +*/ +RUNNER_TEST(MultipleAllowNavigation) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + parser.Parse(miscWidgetsStuff + "configs/MultipleAllowNavigation.xml", + ElementParserPtr( + new RootParser(widgetConfig, + L"widget"))); + + RUNNER_ASSERT(1 == widgetConfig.allowNavigationInfoList.size()); + RUNNER_ASSERT(L"*" == widgetConfig.allowNavigationInfoList.begin()->m_scheme); + RUNNER_ASSERT(L"test1.org" == widgetConfig.allowNavigationInfoList.begin()->m_host); +} + +/* +Name: AllowNavigationMultipleHosts +Description: Tests parsing configuration file with multiple values in allow-navigation element +Expected: Element should be parsed correctly. +*/ +RUNNER_TEST(AllowNavigationMultipleHosts) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + parser.Parse(miscWidgetsStuff + "configs/AllowNavigationMultipleHosts.xml", + ElementParserPtr( + new RootParser(widgetConfig, + L"widget"))); + + RUNNER_ASSERT(4 == widgetConfig.allowNavigationInfoList.size()); + RUNNER_ASSERT(1 == std::count_if(widgetConfig.allowNavigationInfoList.begin(), widgetConfig.allowNavigationInfoList.end(), + AllowNavigationComparator(L"http",L"test2.org"))); + RUNNER_ASSERT(1 == std::count_if(widgetConfig.allowNavigationInfoList.begin(), widgetConfig.allowNavigationInfoList.end(), + AllowNavigationComparator(L"*",L"test3.org"))); + RUNNER_ASSERT(1 == std::count_if(widgetConfig.allowNavigationInfoList.begin(), widgetConfig.allowNavigationInfoList.end(), + AllowNavigationComparator(L"*",L"*.test4.org"))); + RUNNER_ASSERT(1 == std::count_if(widgetConfig.allowNavigationInfoList.begin(), widgetConfig.allowNavigationInfoList.end(), + AllowNavigationComparator(L"*",L"*"))); +} + +/* +Name: AllowNavigationMultipleHosts +Description: Tests parsing configuration file with multiple values in allow-navigation element + with special characters like \n and \t +Expected: Element should be parsed correctly. +*/ +RUNNER_TEST(AllowNavigationMultipleHostsMultiline) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + parser.Parse(miscWidgetsStuff + "configs/AllowNavigationMultipleHostsMultiline.xml", + ElementParserPtr( + new RootParser(widgetConfig, + L"widget"))); + + RUNNER_ASSERT(4 == widgetConfig.allowNavigationInfoList.size()); + RUNNER_ASSERT(1 == std::count_if(widgetConfig.allowNavigationInfoList.begin(), widgetConfig.allowNavigationInfoList.end(), + AllowNavigationComparator(L"http",L"test2.org"))); + RUNNER_ASSERT(1 == std::count_if(widgetConfig.allowNavigationInfoList.begin(), widgetConfig.allowNavigationInfoList.end(), + AllowNavigationComparator(L"*",L"test3.org"))); + RUNNER_ASSERT(1 == std::count_if(widgetConfig.allowNavigationInfoList.begin(), widgetConfig.allowNavigationInfoList.end(), + AllowNavigationComparator(L"*",L"*.test4.org"))); + RUNNER_ASSERT(1 == std::count_if(widgetConfig.allowNavigationInfoList.begin(), widgetConfig.allowNavigationInfoList.end(), + AllowNavigationComparator(L"*",L"*"))); +} diff --git a/tests/general/ParsingAppWidgetTests.cpp b/tests/general/ParsingAppWidgetTests.cpp new file mode 100644 index 0000000..6fbc2df --- /dev/null +++ b/tests/general/ParsingAppWidgetTests.cpp @@ -0,0 +1,1043 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file ParsingAppWidgetTests.cpp + * @author Slawomir Pajak (s.pajak@partner.samsung.com) + * @version 1.0 + * @brief Parsing Tizen app-widget bodies + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace{ + +template +bool checkException(Function fun) +{ + Try + { + fun(); + } + Catch(Exception){ + return true; + } + return false; +} + +} // namespace + +#define RUNNER_ASSERT_EXCEPTION(exceptionType, function) \ + { \ + RUNNER_ASSERT(checkException([&](){function})); \ + } + +using namespace InstallerWrapper; + +//////////////////////////////////////////////////////////////////////////////// + +RUNNER_TEST_GROUP_INIT(ParsingAppWidget) + +/* +Name: InstallWidgetWithAppWidgetFull +Description: Tests if app-widget tag is correctly parsed when all children are included +Expected: widget should be installed. All information should be stored in manifest file +*/ +RUNNER_TEST(InstallWidgetWithAppWidgetFull) +{ + std::string manifestPath = "/opt/share/packages/"; + + std::string tizenId; + RUNNER_ASSERT(install(miscWidgetsStuff + "widgets/appWidgetFull.wgt", tizenId) == InstallerWrapper::Success); + + RUNNER_ASSERT(WrtUtilFileExists(manifestPath.append(tizenId.substr(0, 10)).append(".xml"))); + ManifestFile mf(manifestPath); + WrtDB::WidgetDAOReadOnly dao(DPL::FromASCIIString(tizenId)); + + RUNNER_ASSERT(mf.getValueByXpath("/p:manifest/p:livebox/@appid") == "jeyk39ehc8.appwidget.default"); + RUNNER_ASSERT(mf.getValueByXpath("/p:manifest/p:livebox/@primary") == "true"); + RUNNER_ASSERT(mf.getValueByXpath("/p:manifest/p:livebox/@period") == "1800.0"); + RUNNER_ASSERT(mf.getValueByXpath("/p:manifest/p:livebox/p:launch") == "true"); + RUNNER_ASSERT(mf.getValueByXpath("/p:manifest/p:livebox/p:label") == "My DynamicBox"); + std::string iconPath = DPL::ToUTF8String(*dao.getWidgetInstalledPath()) + WrtDB::GlobalConfig::GetWidgetSharedPath() + + WrtDB::GlobalConfig::GetWidgetDataPath() + "/" + tizenId + ".default.icon.png"; + RUNNER_ASSERT(mf.getValueByXpath("/p:manifest/p:livebox/p:icon") == iconPath); + RUNNER_ASSERT(mf.getValueByXpath("/p:manifest/p:livebox/p:box/@mouse_event") == "false"); + RUNNER_ASSERT(mf.getValueByXpath("/p:manifest/p:livebox/p:box/@touch_effect") == "false"); + std::string boxSrcPath = DPL::ToUTF8String(*dao.getWidgetInstalledPath()) + WrtDB::GlobalConfig::GetWidgetSrcPath() + + "/app-widget/index.html"; + RUNNER_ASSERT(mf.getValueByXpath("/p:manifest/p:livebox/p:box/p:script/@src") == boxSrcPath); + std::string boxPreviewPath = DPL::ToUTF8String(*dao.getWidgetInstalledPath()) + WrtDB::GlobalConfig::GetWidgetSharedPath() + + WrtDB::GlobalConfig::GetWidgetDataPath() + "/" + tizenId + ".default.1x1.preview.png"; + RUNNER_ASSERT(mf.getValueByXpath("/p:manifest/p:livebox/p:box/p:size/@preview") == boxPreviewPath); + RUNNER_ASSERT(mf.getValueByXpath("/p:manifest/p:livebox/p:box/p:size/@need_frame") == "false"); + RUNNER_ASSERT(mf.getValueByXpath("/p:manifest/p:livebox/p:box/p:size") == "1x1"); + std::string pdSrcPath = DPL::ToUTF8String(*dao.getWidgetInstalledPath()) + WrtDB::GlobalConfig::GetWidgetSrcPath() + + "/pd/index.html"; + RUNNER_ASSERT(mf.getValueByXpath("/p:manifest/p:livebox/p:pd/p:script/@src") == pdSrcPath); + RUNNER_ASSERT(mf.getValueByXpath("/p:manifest/p:livebox/p:pd/p:size") == "720x150"); + + RUNNER_ASSERT(uninstall(tizenId)); +} + +/* +Name: InstallWidgetWithAppWidgetMinimal +Description: Tests if app-widget tag is correctly parsed when only mandatory children are included +Expected: widget should be installed. All information should be stored in manifest file +*/ +RUNNER_TEST(InstallWidgetWithAppWidgetMinimal) +{ + std::string manifestPath = "/opt/share/packages/"; + + std::string tizenId; + RUNNER_ASSERT(install(miscWidgetsStuff + "widgets/appWidgetMinimal.wgt", tizenId) == InstallerWrapper::Success); + + RUNNER_ASSERT(WrtUtilFileExists(manifestPath.append(tizenId.substr(0, 10)).append(".xml"))); + ManifestFile mf(manifestPath); + WrtDB::WidgetDAOReadOnly dao(DPL::FromASCIIString(tizenId)); + + RUNNER_ASSERT(mf.getValueByXpath("/p:manifest/p:livebox/@appid") == "djel94jdl9.appwidget.default"); + RUNNER_ASSERT(mf.getValueByXpath("/p:manifest/p:livebox/@primary") == "true"); + RUNNER_ASSERT(mf.getValueByXpath("/p:manifest/p:livebox/p:label") == "My DynamicBox"); + std::string boxSrcPath = DPL::ToUTF8String(*dao.getWidgetInstalledPath()) + WrtDB::GlobalConfig::GetWidgetSrcPath() + + "/app-widget/index.html"; + RUNNER_ASSERT(mf.getValueByXpath("/p:manifest/p:livebox/p:box/p:script/@src") == boxSrcPath); + RUNNER_ASSERT(mf.getValueByXpath("/p:manifest/p:livebox/p:box/p:size") == "1x1"); + + RUNNER_ASSERT(uninstall(tizenId)); +} + +/* +Name: InstallWidgetWithAppWidgetIncorrect +Description: Tests widget installation when app-widget Id and application Id are different +Expected: widget should not be installed. +*/ +RUNNER_TEST(InstallWidgetWithAppWidgetIncorrect) +{ + std::string tizenId; + RUNNER_ASSERT(install(miscWidgetsStuff + "widgets/appWidgetIncorrect.wgt", tizenId) != InstallerWrapper::Success); +} + + +/* +Name: AppWidgetFull +Description: Tests parsing app-widget element with all children +Expected: Elements should be parsed correctly. +*/ +RUNNER_TEST(AppWidgetFull) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + parser.Parse(miscWidgetsStuff + "configs/AppWidgetFull.xml", + ElementParserPtr(new RootParser(widgetConfig, L"widget"))); + + RUNNER_ASSERT(1 == widgetConfig.m_livebox.size()); + RUNNER_ASSERT(L"tizenScmgz.Sample.default" == (**widgetConfig.m_livebox.begin()).m_liveboxId); + RUNNER_ASSERT(L"true" == (**widgetConfig.m_livebox.begin()).m_primary); + RUNNER_ASSERT(L"1800.0" == (**widgetConfig.m_livebox.begin()).m_updatePeriod); + RUNNER_ASSERT(L"true" == (**widgetConfig.m_livebox.begin()).m_autoLaunch); + RUNNER_ASSERT(L"My DynamicBox" == (**widgetConfig.m_livebox.begin()).m_label.begin()->second); + RUNNER_ASSERT(L"box-icon.png" == (**widgetConfig.m_livebox.begin()).m_icon); + RUNNER_ASSERT(L"app-widget/index.html" == (**widgetConfig.m_livebox.begin()).m_boxInfo.m_boxSrc); + RUNNER_ASSERT(L"true" == (**widgetConfig.m_livebox.begin()).m_boxInfo.m_boxMouseEvent); + RUNNER_ASSERT(L"false" == (**widgetConfig.m_livebox.begin()).m_boxInfo.m_boxTouchEffect); + RUNNER_ASSERT(1 == (**widgetConfig.m_livebox.begin()).m_boxInfo.m_boxSize.size()); + RUNNER_ASSERT(L"app-widget/preview-lb1-11.png" == (**widgetConfig.m_livebox.begin()).m_boxInfo.m_boxSize.begin()->m_preview); + RUNNER_ASSERT(L"false" == (**widgetConfig.m_livebox.begin()).m_boxInfo.m_boxSize.begin()->m_useDecoration); + RUNNER_ASSERT(L"1x1" == (**widgetConfig.m_livebox.begin()).m_boxInfo.m_boxSize.begin()->m_size); + RUNNER_ASSERT(L"pd/index.html" == (**widgetConfig.m_livebox.begin()).m_boxInfo.m_pdSrc); + RUNNER_ASSERT(L"720" == (**widgetConfig.m_livebox.begin()).m_boxInfo.m_pdWidth); + RUNNER_ASSERT(L"150" == (**widgetConfig.m_livebox.begin()).m_boxInfo.m_pdHeight); +} + + +/* +Name: AppWidgetMinimal +Description: Tests parsing app-widget element with mandatory children +Expected: Elements should be parsed correctly. +*/ +RUNNER_TEST(AppWidgetMinimal) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + parser.Parse(miscWidgetsStuff + "configs/AppWidgetMinimal.xml", + ElementParserPtr(new RootParser(widgetConfig, L"widget"))); + + RUNNER_ASSERT(1 == widgetConfig.m_livebox.size()); + RUNNER_ASSERT(L"tizenScmgz.Sample.default" == (**widgetConfig.m_livebox.begin()).m_liveboxId); + RUNNER_ASSERT(L"true" == (**widgetConfig.m_livebox.begin()).m_primary); + RUNNER_ASSERT(L"My DynamicBox" == (**widgetConfig.m_livebox.begin()).m_label.begin()->second); + RUNNER_ASSERT(L"app-widget/index.html" == (**widgetConfig.m_livebox.begin()).m_boxInfo.m_boxSrc); + RUNNER_ASSERT(L"1x1" == (**widgetConfig.m_livebox.begin()).m_boxInfo.m_boxSize.begin()->m_size); +} + +/* +Name: AppWidgetIdTooShort +Description: Tests parsing app-widget element with too short id +Expected: Exception should be thrown. +*/ +RUNNER_TEST(AppWidgetIdTooShort) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + RUNNER_ASSERT_EXCEPTION(ElementParser::Exception::ParseError, + parser.Parse(miscWidgetsStuff + "configs/AppWidgetIdTooShort.xml", + ElementParserPtr(new RootParser(widgetConfig, L"widget"))); + ); +} + +/* +Name: AppWidgetIdTooLong +Description: Tests parsing app-widget element with too long id +Expected: Exception should be thrown. +*/ +RUNNER_TEST(AppWidgetIdTooLong) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + RUNNER_ASSERT_EXCEPTION(ElementParser::Exception::ParseError, + parser.Parse(miscWidgetsStuff + "configs/AppWidgetIdTooLong.xml", + ElementParserPtr(new RootParser(widgetConfig, L"widget"))); + ); +} + +/* +Name: AppWidgetIdWrongChar +Description: Tests parsing app-widget element with ill-formed id +Expected: Exception should be thrown. +*/ +RUNNER_TEST(AppWidgetIdWrongChar) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + RUNNER_ASSERT_EXCEPTION(ElementParser::Exception::ParseError, + parser.Parse(miscWidgetsStuff + "configs/AppWidgetIdWrongChar.xml", + ElementParserPtr(new RootParser(widgetConfig, L"widget"))); + ); +} + +/* +Name: AppWidgetIdEmpty +Description: Tests parsing app-widget element with empty id +Expected: Exception should be thrown. +*/ +RUNNER_TEST(AppWidgetIdEmpty) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + RUNNER_ASSERT_EXCEPTION(ElementParser::Exception::ParseError, + parser.Parse(miscWidgetsStuff + "configs/AppWidgetIdEmpty.xml", + ElementParserPtr(new RootParser(widgetConfig, L"widget"))); + ); +} + +/* +Name: AppWidgetNoId +Description: Tests parsing app-widget element without id +Expected: Exception should be thrown. +*/ +RUNNER_TEST(AppWidgetNoId) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + RUNNER_ASSERT_EXCEPTION(ElementParser::Exception::ParseError, + parser.Parse(miscWidgetsStuff + "configs/AppWidgetNoId.xml", + ElementParserPtr(new RootParser(widgetConfig, L"widget"))); + ); +} + +/* +Name: AppWidgetPrimaryWrongValue +Description: Tests parsing app-widget element with wrong primary argument +Expected: Exception should be thrown. +*/ +RUNNER_TEST(AppWidgetPrimaryWrongValue) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + RUNNER_ASSERT_EXCEPTION(ElementParser::Exception::ParseError, + parser.Parse(miscWidgetsStuff + "configs/AppWidgetPrimaryWrongValue.xml", + ElementParserPtr(new RootParser(widgetConfig, L"widget"))); + ); +} + +/* +Name: AppWidgetPrimaryEmpty +Description: Tests parsing app-widget element with empty primary argument +Expected: Exception should be thrown. +*/ +RUNNER_TEST(AppWidgetPrimaryEmpty) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + RUNNER_ASSERT_EXCEPTION(ElementParser::Exception::ParseError, + parser.Parse(miscWidgetsStuff + "configs/AppWidgetPrimaryEmpty.xml", + ElementParserPtr(new RootParser(widgetConfig, L"widget"))); + ); +} + +/* +Name: AppWidgetNoPrimary +Description: Tests parsing app-widget element without primary argument +Expected: Exception should be thrown. +*/ +RUNNER_TEST(AppWidgetNoPrimary) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + RUNNER_ASSERT_EXCEPTION(ElementParser::Exception::ParseError, + parser.Parse(miscWidgetsStuff + "configs/AppWidgetNoPrimary.xml", + ElementParserPtr(new RootParser(widgetConfig, L"widget"))); + ); +} + +/* +Name: AppWidgetMultiplePrimary +Description: Tests parsing configuration with multiple app-widget element. +Expected: Parsing should be successful. +*/ +RUNNER_TEST(AppWidgetMultiplePrimary) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + parser.Parse(miscWidgetsStuff + "configs/AppWidgetMultiplePrimary.xml", + ElementParserPtr(new RootParser(widgetConfig, L"widget"))); + + RUNNER_ASSERT(3 == widgetConfig.m_livebox.size()); + RUNNER_ASSERT(2 == std::count_if(widgetConfig.m_livebox.begin(), widgetConfig.m_livebox.end(), + [](const WrtDB::ConfigParserData::OptionalLiveboxInfo& liveBox){ + return liveBox->m_primary == L"true"; + }) + ); + RUNNER_ASSERT(1 == std::count_if(widgetConfig.m_livebox.begin(), widgetConfig.m_livebox.end(), + [](const WrtDB::ConfigParserData::OptionalLiveboxInfo& liveBox){ + return liveBox->m_primary == L"false"; + }) + ); +} + +/* +Name: AppWidgetUpdatePeriodLow +Description: Tests parsing app-widget element with update-period argument too low +Expected: Parsing should be successful. updatePeriod should have low boundary value. +*/ +RUNNER_TEST(AppWidgetUpdatePeriodLow) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + parser.Parse(miscWidgetsStuff + "configs/AppWidgetUpdatePeriodLow.xml", + ElementParserPtr(new RootParser(widgetConfig, L"widget"))); + + RUNNER_ASSERT(1 == widgetConfig.m_livebox.size()); + RUNNER_ASSERT(L"1800.0" == (**widgetConfig.m_livebox.begin()).m_updatePeriod); +} + +/* +Name: AppWidgetUpdatePeriodWrongFormat +Description: Tests parsing app-widget element with wrong update-period argument. +Expected: Exception should be thrown. +*/ +RUNNER_TEST(AppWidgetUpdatePeriodWrongFormat) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + RUNNER_ASSERT_EXCEPTION(ElementParser::Exception::ParseError, + parser.Parse(miscWidgetsStuff + "configs/AppWidgetUpdatePeriodWrongFormat.xml", + ElementParserPtr(new RootParser(widgetConfig, L"widget"))); + ); +} + +/* +Name: AppWidgetUpdatePeriodEmpty +Description: Tests parsing app-widget element with empty update-period argument. +Expected: Parsing should be successful. updatePeriod should have empty value. +*/ +RUNNER_TEST(AppWidgetUpdatePeriodEmpty) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + parser.Parse(miscWidgetsStuff + "configs/AppWidgetUpdatePeriodEmpty.xml", + ElementParserPtr(new RootParser(widgetConfig, L"widget"))); + + RUNNER_ASSERT(1 == widgetConfig.m_livebox.size()); + RUNNER_ASSERT((**widgetConfig.m_livebox.begin()).m_updatePeriod.empty()); +} + +/* +Name: RUNNER_TEST(AppWidgetAutoLaunchWrongValue) +Description: Tests parsing app-widget element with wrong auto-launch argument. +Expected: Exception should be thrown. +*/ +RUNNER_TEST(AppWidgetAutoLaunchWrongValue) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + RUNNER_ASSERT_EXCEPTION(ElementParser::Exception::ParseError, + parser.Parse(miscWidgetsStuff + "configs/AppWidgetAutoLaunchWrongValue.xml", + ElementParserPtr(new RootParser(widgetConfig, L"widget"))); + ); +} + +/* +Name: AppWidgetAutoLaunchEmpty +Description: Tests parsing app-widget element with empty auto-launch argument. +Expected: Parsing should be successful. auto-launch should have empty value. +*/ +RUNNER_TEST(AppWidgetAutoLaunchEmpty) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + parser.Parse(miscWidgetsStuff + "configs/AppWidgetAutoLaunchEmpty.xml", + ElementParserPtr(new RootParser(widgetConfig, L"widget"))); + + RUNNER_ASSERT(1 == widgetConfig.m_livebox.size()); + RUNNER_ASSERT(L"false" == (**widgetConfig.m_livebox.begin()).m_autoLaunch); +} + +/* +Name: BoxLabelEmpty +Description: Tests parsing empty box-label element. +Expected: Parsing should be successful. label should have empty value. +*/ +RUNNER_TEST(BoxLabelEmpty) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + parser.Parse(miscWidgetsStuff + "configs/BoxLabelEmpty.xml", + ElementParserPtr(new RootParser(widgetConfig, L"widget"))); + + RUNNER_ASSERT(1 == widgetConfig.m_livebox.size()); + RUNNER_ASSERT(1 == (**widgetConfig.m_livebox.begin()).m_label.size()); + RUNNER_ASSERT((**widgetConfig.m_livebox.begin()).m_label.begin()->first.empty()); + RUNNER_ASSERT((**widgetConfig.m_livebox.begin()).m_label.begin()->second.empty()); +} + +/* +Name: AppWidgetNoBoxLabel +Description: Tests parsing app-widget element without box-label element. +Expected: Exception should be thrown. +*/ +RUNNER_TEST(AppWidgetNoBoxLabel) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + RUNNER_ASSERT_EXCEPTION(ElementParser::Exception::ParseError, + parser.Parse(miscWidgetsStuff + "configs/AppWidgetNoBoxLabel.xml", + ElementParserPtr(new RootParser(widgetConfig, L"widget"))); + ); +} + +/* +Name: AppWidgetMultipleBoxLabel +Description: Tests parsing app-widget element with multiple box-label element. +Expected: Parsing should be successful and elements stored correctly. +*/ +RUNNER_TEST(AppWidgetMultipleBoxLabel) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + parser.Parse(miscWidgetsStuff + "configs/AppWidgetMultipleBoxLabel.xml", + ElementParserPtr(new RootParser(widgetConfig, L"widget"))); + + RUNNER_ASSERT(1 == widgetConfig.m_livebox.size()); + RUNNER_ASSERT(3 == (**widgetConfig.m_livebox.begin()).m_label.size()); + + RUNNER_ASSERT( + 1 == std::count((**widgetConfig.m_livebox.begin()).m_label.begin(), (**widgetConfig.m_livebox.begin()).m_label.end(), + std::pair(L"en",L"test_en") )); + RUNNER_ASSERT( + 1 == std::count((**widgetConfig.m_livebox.begin()).m_label.begin(), (**widgetConfig.m_livebox.begin()).m_label.end(), + std::pair(L"pl",L"test_pl") )); + RUNNER_ASSERT( + 1 == std::count((**widgetConfig.m_livebox.begin()).m_label.begin(), (**widgetConfig.m_livebox.begin()).m_label.end(), + std::pair(L"",L"test") )); + +} + +/* +Name: BoxIconEmpty +Description: Tests parsing empty box-icon element. +Expected: Exception should be thrown. +*/ +RUNNER_TEST(BoxIconEmpty) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + RUNNER_ASSERT_EXCEPTION(ElementParser::Exception::ParseError, + parser.Parse(miscWidgetsStuff + "configs/BoxIconEmpty.xml", + ElementParserPtr(new RootParser(widgetConfig, L"widget"))); + ); +} + +/* +Name: BoxIconSrcEmpty +Description: Tests parsing box-icon element with empty src attribute. +Expected: Exception should be thrown. +*/ +RUNNER_TEST(BoxIconSrcEmpty) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + RUNNER_ASSERT_EXCEPTION(ElementParser::Exception::ParseError, + parser.Parse(miscWidgetsStuff + "configs/BoxIconSrcEmpty.xml", + ElementParserPtr(new RootParser(widgetConfig, L"widget"))); + ); +} + +/* +Name: AppWidgetMultipleBoxIcon +Description: Tests parsing app-widget with multiple box-icon elements. +Expected: Exception should be thrown. +*/ +RUNNER_TEST(AppWidgetMultipleBoxIcon) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + RUNNER_ASSERT_EXCEPTION(ElementParser::Exception::ParseError, + parser.Parse(miscWidgetsStuff + "configs/AppWidgetMultipleBoxIcon.xml", + ElementParserPtr(new RootParser(widgetConfig, L"widget"))); + ); +} + +/* +Name: AppWidgetNoBoxContent +Description: Tests parsing app-widget without box-content element. +Expected: Exception should be thrown. +*/ +RUNNER_TEST(AppWidgetNoBoxContent) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + RUNNER_ASSERT_EXCEPTION(ElementParser::Exception::ParseError, + parser.Parse(miscWidgetsStuff + "configs/AppWidgetNoBoxContent.xml", + ElementParserPtr(new RootParser(widgetConfig, L"widget"))); + ); +} + + +/* +Name: AppWidgetMultipleBoxContent +Description: Tests parsing app-widget with multiple box-content element. +Expected: Exception should be thrown. +*/ +RUNNER_TEST(AppWidgetMultipleBoxContent) +{ + + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + RUNNER_ASSERT_EXCEPTION(ElementParser::Exception::ParseError, + parser.Parse(miscWidgetsStuff + "configs/AppWidgetMultipleBoxContent.xml", + ElementParserPtr(new RootParser(widgetConfig, L"widget"))); + ); +} + + +/* +Name: BoxContentEmpty +Description: Tests parsing empty box-content element. +Expected: Exception should be thrown. +*/ +RUNNER_TEST(BoxContentEmpty) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + RUNNER_ASSERT_EXCEPTION(ElementParser::Exception::ParseError, + parser.Parse(miscWidgetsStuff + "configs/BoxContentEmpty.xml", + ElementParserPtr(new RootParser(widgetConfig, L"widget"))); + ); +} + +/* +Name: BoxContentNoSrc +Description: Tests parsing box-content element without src attribute. +Expected: Exception should be thrown. +*/ +RUNNER_TEST(BoxContentNoSrc) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + RUNNER_ASSERT_EXCEPTION(ElementParser::Exception::ParseError, + parser.Parse(miscWidgetsStuff + "configs/BoxContentNoSrc.xml", + ElementParserPtr(new RootParser(widgetConfig, L"widget"))); + ); +} + +/* +Name: BoxContentSrcEmpty +Description: Tests parsing box-content element with empty src attribute. +Expected: Exception should be thrown. +*/ +RUNNER_TEST(BoxContentSrcEmpty) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + RUNNER_ASSERT_EXCEPTION(ElementParser::Exception::ParseError, + parser.Parse(miscWidgetsStuff + "configs/BoxContentSrcEmpty.xml", + ElementParserPtr(new RootParser(widgetConfig, L"widget"))); + ); +} + +/* +Name: BoxContentNoMouseEvent +Description: Tests parsing box-content element without mouse-event attribute. +Expected: Parsing should be successful. boxMouseEvent should have default value. +*/ +RUNNER_TEST(BoxContentNoMouseEvent) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + parser.Parse(miscWidgetsStuff + "configs/BoxContentNoMouseEvent.xml", + ElementParserPtr(new RootParser(widgetConfig, L"widget"))); + + RUNNER_ASSERT(1 == widgetConfig.m_livebox.size()); + RUNNER_ASSERT(L"false" == (**widgetConfig.m_livebox.begin()).m_boxInfo.m_boxMouseEvent); +} + +/* +Name: BoxContentMouseEventEmpty +Description: Tests parsing box-content element with empty mouse-event attribute. +Expected: Parsing should be successful. boxMouseEvent should have default value. +*/ +RUNNER_TEST(BoxContentMouseEventEmpty) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + parser.Parse(miscWidgetsStuff + "configs/BoxContentMouseEventEmpty.xml", + ElementParserPtr(new RootParser(widgetConfig, L"widget"))); + + RUNNER_ASSERT(1 == widgetConfig.m_livebox.size()); + RUNNER_ASSERT(L"false" == (**widgetConfig.m_livebox.begin()).m_boxInfo.m_boxMouseEvent); +} + +/* +Name: BoxContentMouseEventWrongValue +Description: Tests parsing box-content element with wrong mouse-event attribute. +Expected: Exception should be thrown. +*/ +RUNNER_TEST(BoxContentMouseEventWrongValue) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + RUNNER_ASSERT_EXCEPTION(ElementParser::Exception::ParseError, + parser.Parse(miscWidgetsStuff + "configs/BoxContentMouseEventWrongValue.xml", + ElementParserPtr(new RootParser(widgetConfig, L"widget"))); + ); +} + +/* +Name: BoxContentNoTouchEfect +Description: Tests parsing box-content element without touch-effect attribute. +Expected: Parsing should be successful. boxTouchEffect should have default value. +*/ +RUNNER_TEST(BoxContentNoTouchEfect) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + parser.Parse(miscWidgetsStuff + "configs/BoxContentNoTouchEfect.xml", + ElementParserPtr(new RootParser(widgetConfig, L"widget"))); + + RUNNER_ASSERT(1 == widgetConfig.m_livebox.size()); + RUNNER_ASSERT(L"true" == (**widgetConfig.m_livebox.begin()).m_boxInfo.m_boxTouchEffect); +} + +/* +Name: BoxContentTouchEfectEmpty +Description: Tests parsing box-content element with empty touch-effect attribute. +Expected: Parsing should be successful. boxTouchEffect should have default value. +*/ +RUNNER_TEST(BoxContentTouchEfectEmpty) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + parser.Parse(miscWidgetsStuff + "configs/BoxContentTouchEfectEmpty.xml", + ElementParserPtr(new RootParser(widgetConfig, L"widget"))); + + RUNNER_ASSERT(1 == widgetConfig.m_livebox.size()); + RUNNER_ASSERT(L"true" == (**widgetConfig.m_livebox.begin()).m_boxInfo.m_boxTouchEffect); +} + +/* +Name: BoxContentTouchEfectWrongValue +Description: Tests parsing box-content element with wrong touch-effect attribute. +Expected: Exception should be thrown. +*/ +RUNNER_TEST(BoxContentTouchEfectWrongValue) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + RUNNER_ASSERT_EXCEPTION(ElementParser::Exception::ParseError, + parser.Parse(miscWidgetsStuff + "configs/BoxContentTouchEfectWrongValue.xml", + ElementParserPtr(new RootParser(widgetConfig, L"widget"))); + ); +} + +/* +Name: BoxContentMultipleBoxSize +Description: Tests parsing box-content element with multiple box-size elements. +Expected: Parsing should be successful. +*/ +RUNNER_TEST(BoxContentMultipleBoxSize) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + parser.Parse(miscWidgetsStuff + "configs/BoxContentMultipleBoxSize.xml", + ElementParserPtr(new RootParser(widgetConfig, L"widget"))); + + RUNNER_ASSERT(1 == widgetConfig.m_livebox.size()); + RUNNER_ASSERT(3 == (**widgetConfig.m_livebox.begin()).m_boxInfo.m_boxSize.size()); + + RUNNER_ASSERT(1 == std::count_if((**widgetConfig.m_livebox.begin()).m_boxInfo.m_boxSize.begin(), + (**widgetConfig.m_livebox.begin()).m_boxInfo.m_boxSize.end(), + [](const WrtDB::ConfigParserData::LiveboxInfo::BoxSizeInfo& boxSize){ + return boxSize.m_size == L"1x1"; + }) + ); + RUNNER_ASSERT(1 == std::count_if((**widgetConfig.m_livebox.begin()).m_boxInfo.m_boxSize.begin(), + (**widgetConfig.m_livebox.begin()).m_boxInfo.m_boxSize.end(), + [](const WrtDB::ConfigParserData::LiveboxInfo::BoxSizeInfo& boxSize){ + return boxSize.m_size == L"2x1"; + }) + ); + RUNNER_ASSERT(1 == std::count_if((**widgetConfig.m_livebox.begin()).m_boxInfo.m_boxSize.begin(), + (**widgetConfig.m_livebox.begin()).m_boxInfo.m_boxSize.end(), + [](const WrtDB::ConfigParserData::LiveboxInfo::BoxSizeInfo& boxSize){ + return boxSize.m_size == L"2x2"; + }) + ); +} + +/* +Name: BoxSizeEmpty +Description: Tests parsing empty box-size element. +Expected: Exception should be thrown. +*/ +RUNNER_TEST(BoxSizeEmpty) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + RUNNER_ASSERT_EXCEPTION(ElementParser::Exception::ParseError, + parser.Parse(miscWidgetsStuff + "configs/BoxSizeEmpty.xml", + ElementParserPtr(new RootParser(widgetConfig, L"widget"))); + ); +} + +/* +Name: BoxSizePreviewEmpty +Description: Tests parsing box-size element with empty preview attribute. +Expected: Parsing should be successful. Preview value should be empty +*/ +RUNNER_TEST(BoxSizePreviewEmpty) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + parser.Parse(miscWidgetsStuff + "configs/BoxSizePreviewEmpty.xml", + ElementParserPtr(new RootParser(widgetConfig, L"widget"))); + RUNNER_ASSERT(1 == widgetConfig.m_livebox.size()); + RUNNER_ASSERT(1 == (**widgetConfig.m_livebox.begin()).m_boxInfo.m_boxSize.size()); + RUNNER_ASSERT((**widgetConfig.m_livebox.begin()).m_boxInfo.m_boxSize.begin()->m_preview.empty()); +} + +/* +Name: BoxSizeNoUserDecoration +Description: Tests parsing box-size element without use-decoration attribute. +Expected: Parsing should be successful. useDecoration should be set to default value +*/ +RUNNER_TEST(BoxSizeNoUserDecoration) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + parser.Parse(miscWidgetsStuff + "configs/BoxSizeNoUserDecoration.xml", + ElementParserPtr(new RootParser(widgetConfig, L"widget"))); + RUNNER_ASSERT(1 == widgetConfig.m_livebox.size()); + RUNNER_ASSERT(1 == (**widgetConfig.m_livebox.begin()).m_boxInfo.m_boxSize.size()); + RUNNER_ASSERT(L"true" == (**widgetConfig.m_livebox.begin()).m_boxInfo.m_boxSize.begin()->m_useDecoration); +} + +/* +Name: BoxSizeUserDecorationEmpty +Description: Tests parsing box-size element with empty use-decoration attribute. +Expected: Parsing should be successful. useDecoration should be set to default value +*/ +RUNNER_TEST(BoxSizeUserDecorationEmpty) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + parser.Parse(miscWidgetsStuff + "configs/BoxSizeUserDecorationEmpty.xml", + ElementParserPtr(new RootParser(widgetConfig, L"widget"))); + RUNNER_ASSERT(1 == widgetConfig.m_livebox.size()); + RUNNER_ASSERT(1 == (**widgetConfig.m_livebox.begin()).m_boxInfo.m_boxSize.size()); + RUNNER_ASSERT(L"true" == (**widgetConfig.m_livebox.begin()).m_boxInfo.m_boxSize.begin()->m_useDecoration); +} + +/* +Name: BoxContentMultiplePd +Description: Tests parsing box-content element with multiple pd element. +Expected: Exception should be thrown +*/ +RUNNER_TEST(BoxContentMultiplePd) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + RUNNER_ASSERT_EXCEPTION(ElementParser::Exception::ParseError, + parser.Parse(miscWidgetsStuff + "configs/BoxContentMultiplePd.xml", + ElementParserPtr(new RootParser(widgetConfig, L"widget"))); + ); +} + +/* +Name: PdNoSrc +Description: Tests parsing pd element without src attribute. +Expected: Exception should be thrown +*/ +RUNNER_TEST(PdNoSrc) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + RUNNER_ASSERT_EXCEPTION(ElementParser::Exception::ParseError, + parser.Parse(miscWidgetsStuff + "configs/PdNoSrc.xml", + ElementParserPtr(new RootParser(widgetConfig, L"widget"))); + ); +} + +/* +Name: PdSrcEmpty +Description: Tests parsing pd element with empty src attribute. +Expected: Exception should be thrown +*/ +RUNNER_TEST(PdSrcEmpty) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + RUNNER_ASSERT_EXCEPTION(ElementParser::Exception::ParseError, + parser.Parse(miscWidgetsStuff + "configs/PdSrcEmpty.xml", + ElementParserPtr(new RootParser(widgetConfig, L"widget"))); + ); +} + +/* +Name: PdNoWidth +Description: Tests parsing pd element without width attribute. +Expected: Exception should be thrown +*/ +RUNNER_TEST(PdNoWidth) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + RUNNER_ASSERT_EXCEPTION(ElementParser::Exception::ParseError, + parser.Parse(miscWidgetsStuff + "configs/PdNoWidth.xml", + ElementParserPtr(new RootParser(widgetConfig, L"widget"))); + ); +} + +/* +Name: PdWidthEmpty +Description: Tests parsing pd element with empty width attribute. +Expected: Exception should be thrown +*/ +RUNNER_TEST(PdWidthEmpty) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + RUNNER_ASSERT_EXCEPTION(ElementParser::Exception::ParseError, + parser.Parse(miscWidgetsStuff + "configs/PdWidthEmpty.xml", + ElementParserPtr(new RootParser(widgetConfig, L"widget"))); + ); +} + +/* +Name: PdWidthZero +Description: Tests parsing pd element with width zero value. +Expected: Parsing should be successful. +*/ +RUNNER_TEST(PdWidthZero) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + parser.Parse(miscWidgetsStuff + "configs/PdWidthZero.xml", + ElementParserPtr(new RootParser(widgetConfig, L"widget"))); + + RUNNER_ASSERT(1 == widgetConfig.m_livebox.size()); + RUNNER_ASSERT(L"0" == (**widgetConfig.m_livebox.begin()).m_boxInfo.m_pdWidth); +} + +/* +Name: PdWidthNegative +Description: Tests parsing pd element with width negative value. +Expected: Parsing should be successful. +*/ +RUNNER_TEST(PdWidthNegative) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + parser.Parse(miscWidgetsStuff + "configs/PdWidthNegative.xml", + ElementParserPtr(new RootParser(widgetConfig, L"widget"))); + + RUNNER_ASSERT(1 == widgetConfig.m_livebox.size()); + RUNNER_ASSERT(L"-1" == (**widgetConfig.m_livebox.begin()).m_boxInfo.m_pdWidth); +} + +/* +Name: PdWidthWrongValue +Description: Tests parsing pd element with width wrong value. +Expected: Exception should be thrown +*/ +RUNNER_TEST(PdWidthWrongValue) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + RUNNER_ASSERT_EXCEPTION(ElementParser::Exception::ParseError, + parser.Parse(miscWidgetsStuff + "configs/PdWidthWrongValue.xml", + ElementParserPtr(new RootParser(widgetConfig, L"widget"))); + ); +} + +/* +Name: PdNoHeight +Description: Tests parsing pd element without height attribute. +Expected: Exception should be thrown +*/ +RUNNER_TEST(PdNoHeight) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + RUNNER_ASSERT_EXCEPTION(ElementParser::Exception::ParseError, + parser.Parse(miscWidgetsStuff + "configs/PdNoHeight.xml", + ElementParserPtr(new RootParser(widgetConfig, L"widget"))); + ); +} + +/* +Name: PdHeightEmpty +Description: Tests parsing pd element with empty height attribute. +Expected: Exception should be thrown +*/ +RUNNER_TEST(PdHeightEmpty) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + RUNNER_ASSERT_EXCEPTION(ElementParser::Exception::ParseError, + parser.Parse(miscWidgetsStuff + "configs/PdHeightEmpty.xml", + ElementParserPtr(new RootParser(widgetConfig, L"widget"))); + ); +} + +/* +Name: PdHeightTooLow +Description: Tests parsing pd element with height attribute below range. +Expected: Parsing should be successful. Height should have low boundary value. +*/ +RUNNER_TEST(PdHeightTooLow) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + parser.Parse(miscWidgetsStuff + "configs/PdHeightTooLow.xml", + ElementParserPtr(new RootParser(widgetConfig, L"widget"))); + + RUNNER_ASSERT(1 == widgetConfig.m_livebox.size()); + RUNNER_ASSERT(L"1" == (**widgetConfig.m_livebox.begin()).m_boxInfo.m_pdHeight); +} + +/* +Name: PdHeightExcessive +Description: Tests parsing pd element with height attribute with value above range. +Expected: Parsing should be successful. Height should have high boundary value. +*/ +RUNNER_TEST(PdHeightExcessive) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + parser.Parse(miscWidgetsStuff + "configs/PdHeightExcessive.xml", + ElementParserPtr(new RootParser(widgetConfig, L"widget"))); + + RUNNER_ASSERT(1 == widgetConfig.m_livebox.size()); + RUNNER_ASSERT(L"380" == (**widgetConfig.m_livebox.begin()).m_boxInfo.m_pdHeight); +} + +/* +Name: PdHeightWrongValue +Description: Tests parsing pd element with wrong height attribute. +Expected: Exception should be thrown +*/ +RUNNER_TEST(PdHeightWrongValue) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + RUNNER_ASSERT_EXCEPTION(ElementParser::Exception::ParseError, + parser.Parse(miscWidgetsStuff + "configs/PdHeightWrongValue.xml", + ElementParserPtr(new RootParser(widgetConfig, L"widget"))); + ); +} diff --git a/tests/general/ParsingCategoryTests.cpp b/tests/general/ParsingCategoryTests.cpp new file mode 100644 index 0000000..a376807 --- /dev/null +++ b/tests/general/ParsingCategoryTests.cpp @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file ParsingCategoryTests.cpp + * @author Slawomir Pajak (s.pajak@partner.samsung.com) + * @version 1.0 + * @brief Category element installation tests + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +using namespace InstallerWrapper; + +//////////////////////////////////////////////////////////////////////////////// + +RUNNER_TEST_GROUP_INIT(ParsingCategory) + +/* +Name: InstallWidgetWithCategory +Description: Tests if widget with category is installed correctly +Expected: widget should be installed correctly and category should be present in manifest file +*/ +RUNNER_TEST(InstallWidgetWithCategory) +{ + std::string tizenId; + std::string manifestPath = "/opt/share/packages/"; + RUNNER_ASSERT(install(miscWidgetsStuff + "widgets/category.wgt", tizenId) == InstallerWrapper::Success); + + RUNNER_ASSERT(WrtUtilFileExists(manifestPath.append(tizenId.substr(0, 10)).append(".xml"))); + ManifestFile mf(manifestPath); + + RUNNER_ASSERT(mf.getValueByXpath("/p:manifest/p:ui-application/p:category[1]/@name") == "testCategory"); + uninstall(tizenId); +} + + +/* +Name: CategoryElementOk +Description: Tests parsing correct category element +Expected: Element should be parsed correcty. +*/ +RUNNER_TEST(CategoryElementOk) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + parser.Parse(miscWidgetsStuff + "configs/config_category1.xml", + ElementParserPtr( + new RootParser(widgetConfig, + L"widget"))); + + RUNNER_ASSERT(2 == widgetConfig.categoryList.size()); + RUNNER_ASSERT(std::count(widgetConfig.categoryList.begin(), widgetConfig.categoryList.end(), L"testCategory1") == 1); + RUNNER_ASSERT(std::count(widgetConfig.categoryList.begin(), widgetConfig.categoryList.end(), L"testCategory2") == 1); +} + +/* +Name: CategoryElementEmptyName +Description: Tests parsing splash element with empty name attribute +Expected: No exception and categoryList should be empty +*/ +RUNNER_TEST(CategoryElementEmptyName) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + parser.Parse(miscWidgetsStuff + "configs/config_category2.xml", + ElementParserPtr( + new RootParser(widgetConfig, + DPL:: + FromUTF32String( + L"widget")))); + + RUNNER_ASSERT(widgetConfig.categoryList.empty()); +} + +/* +Name: CategoryElementNoName +Description: Tests parsing category element with no name attribute +Expected: No exception and categoryList should be empty +*/ +RUNNER_TEST(CategoryElementNoName) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + parser.Parse(miscWidgetsStuff + "configs/config_category3.xml", + ElementParserPtr( + new RootParser(widgetConfig, + DPL:: + FromUTF32String( + L"widget")))); + + RUNNER_ASSERT(widgetConfig.categoryList.empty()); +} + +/* +Name: CategoryElementDuplicated +Description: Tests parsing three category elements (two are identical) +Expected: No exception and categoryList should have two distinct elements +*/ +RUNNER_TEST(CategoryElementDuplicated) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + parser.Parse(miscWidgetsStuff + "configs/config_category4.xml", + ElementParserPtr( + new RootParser(widgetConfig, + DPL:: + FromUTF32String( + L"widget")))); + + RUNNER_ASSERT(2 == widgetConfig.categoryList.size()); + RUNNER_ASSERT(std::count(widgetConfig.categoryList.begin(), widgetConfig.categoryList.end(), L"testCategory1") == 1); + RUNNER_ASSERT(std::count(widgetConfig.categoryList.begin(), widgetConfig.categoryList.end(), L"testCategory2") == 1); + +} diff --git a/tests/general/ParsingContentTests.cpp b/tests/general/ParsingContentTests.cpp new file mode 100644 index 0000000..56b114e --- /dev/null +++ b/tests/general/ParsingContentTests.cpp @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file ParsingContentTests.cpp + * @author Slawomir Pajak (s.pajak@partner.samsung.com) + * @version 1.0 + * @brief content element installation tests + */ + +#include +#include +#include +#include + +#include +#include +#include + +using namespace InstallerWrapper; + +namespace{ + +template +bool checkException(Function fun) +{ + Try + { + fun(); + } + Catch(Exception){ + return true; + } + return false; +} + +} // namespace + +#define RUNNER_ASSERT_EXCEPTION(exceptionType, function) \ + { \ + RUNNER_ASSERT(checkException([&](){function})); \ + } + + + +//////////////////////////////////////////////////////////////////////////////// + +RUNNER_TEST_GROUP_INIT(ParsingContent) + +/* +Name: InstallWidgetWithContentCorrect +Description: Tests if widget with correct content element is installed correctly +Expected: widget should be installed correctly and startFile info should be stored in database +*/ +RUNNER_TEST(InstallWidgetWithContentCorrect) +{ + std::string tizenId; + std::string manifestPath = "/opt/share/packages/"; + RUNNER_ASSERT(install(miscWidgetsStuff + "widgets/contentCorrect.wgt", tizenId) == InstallerWrapper::Success); + + WrtDB::WidgetDAOReadOnly dao(DPL::FromASCIIString(tizenId)); + WrtDB::WidgetDAOReadOnly::WidgetStartFileList startFileList = dao.getStartFileList(); + + RUNNER_ASSERT(6 == startFileList.size()); + RUNNER_ASSERT( + 1 == std::count_if(startFileList.begin(), startFileList.end(), + [](const WrtDB::WidgetDAOReadOnly::WidgetStartFileRow& startFileRow){ + return L"http://test.org" == startFileRow.src; + }) + ); + + + uninstall(tizenId); +} + +/* +Name: InstallWidgetWithContentIncorrect +Description: Tests if widget with incorrect content element is not installed correctly +Expected: widget should not be installed +*/ +RUNNER_TEST(InstallWidgetWithContentIncorrect) +{ + std::string tizenId; + std::string manifestPath = "/opt/share/packages/"; + RUNNER_ASSERT(install(miscWidgetsStuff + "widgets/contentIncorrect.wgt", tizenId) == InstallerWrapper::OtherError); +} + +/* +Name: NoContent +Description: Tests parsing configuration file without content element +Expected: Element should be parsed correctly. +*/ +RUNNER_TEST(NoContent) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + parser.Parse(miscWidgetsStuff + "configs/NoContent.xml", + ElementParserPtr( + new RootParser(widgetConfig, + L"widget"))); + + RUNNER_ASSERT(widgetConfig.metadataList.empty()); +} + +/* +Name: ContentEmpty +Description: Tests parsing configuration file with empty content element +Expected: Exception should be thrown +*/ +RUNNER_TEST(ContentEmpty) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + RUNNER_ASSERT_EXCEPTION(ElementParser::Exception::ParseError, + parser.Parse(miscWidgetsStuff + "configs/ContentEmpty.xml", + ElementParserPtr( new RootParser(widgetConfig, L"widget"))); + ); +} + +/* +Name: ContentSrcEmpty +Description: Tests parsing configuration file with empty src attribute in content element +Expected: Exception should be thrown +*/ +RUNNER_TEST(ContentSrcEmpty) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + RUNNER_ASSERT_EXCEPTION(ElementParser::Exception::ParseError, + parser.Parse(miscWidgetsStuff + "configs/ContentSrcEmpty.xml", + ElementParserPtr( new RootParser(widgetConfig, L"widget"))); + ); +} + +/* +Name: ContentSrcCorrect +Description: Tests parsing configuration file with correct content element +Expected: Element should be parsed correctly. +*/ +RUNNER_TEST(ContentSrcCorrect) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + parser.Parse(miscWidgetsStuff + "configs/ContentSrcCorrect.xml", + ElementParserPtr(new RootParser(widgetConfig, L"widget"))); + + RUNNER_ASSERT(DPL::OptionalString(L"http://test.org") == widgetConfig.startFile); +} + +/* +Name: MultipleContentCorrect +Description: Tests parsing configuration file with multiple content element +Expected: Element should be parsed correctly. +*/ +RUNNER_TEST(MultipleContentCorrect) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + parser.Parse(miscWidgetsStuff + "configs/MultipleContentCorrect.xml", + ElementParserPtr(new RootParser(widgetConfig, L"widget"))); + + RUNNER_ASSERT(DPL::OptionalString(L"http://test.org") == widgetConfig.startFile); +} + +/* +Name: MultipleContentCorrect +Description: Tests parsing configuration file with multiple content element. + First occurrence is incorrect +Expected: Exception should be thrown +*/ +RUNNER_TEST(MultipleContentIncorrect) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + RUNNER_ASSERT_EXCEPTION(ElementParser::Exception::ParseError, + parser.Parse(miscWidgetsStuff + "configs/MultipleContentIncorrect.xml", + ElementParserPtr( new RootParser(widgetConfig, L"widget"))); + ); +} diff --git a/tests/general/ParsingCspTests.cpp b/tests/general/ParsingCspTests.cpp new file mode 100644 index 0000000..0dcbf3e --- /dev/null +++ b/tests/general/ParsingCspTests.cpp @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file ParsingCspTests.cpp + * @author Slawomir Pajak (s.pajak@partner.samsung.com) + * @version 1.0 + * @brief content-security-policy and content-security-policy-report-only element installation + * tests + */ + +#include +#include +#include +#include + +#include +#include +#include + +using namespace InstallerWrapper; + +//////////////////////////////////////////////////////////////////////////////// + +RUNNER_TEST_GROUP_INIT(ParsingCsp) + +/* +Name: InstallWidgetWithCsp +Description: Tests if widget with content-security-policy and content-security-policy-report-only is installed correctly +Expected: widget should be installed correctly and CSP values should be correctly stored in database +*/ +RUNNER_TEST(InstallWidgetWithCsp) +{ + std::string tizenId; + RUNNER_ASSERT(install(miscWidgetsStuff + "widgets/csp.wgt", tizenId) == InstallerWrapper::Success); + + WrtDB::WidgetDAOReadOnly dao(DPL::FromASCIIString(tizenId)); + + RUNNER_ASSERT(L"testCSP" == *dao.getCspPolicy()); + RUNNER_ASSERT(L"testCSPro" == *dao.getCspPolicyReportOnly()); + + uninstall(tizenId); +} + + +/* +Name: NoCsp +Description: Tests parsing configuration file without content-security-policy and content-security-policy-report-only element +Expected: Element should be parsed correctly. +*/ +RUNNER_TEST(NoCsp) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + parser.Parse(miscWidgetsStuff + "configs/NoCsp.xml", + ElementParserPtr( + new RootParser(widgetConfig, + L"widget"))); + + RUNNER_ASSERT(!widgetConfig.cspPolicy); + RUNNER_ASSERT(!widgetConfig.cspPolicyReportOnly); +} + +/* +Name: CspEmpty +Description: Tests parsing configuration file with empty content-security-policy element +Expected: Element should be parsed correctly. +*/ +RUNNER_TEST(CspEmpty) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + parser.Parse(miscWidgetsStuff + "configs/CspEmpty.xml", + ElementParserPtr( + new RootParser(widgetConfig, + L"widget"))); + + RUNNER_ASSERT(!widgetConfig.cspPolicy); + RUNNER_ASSERT(!widgetConfig.cspPolicyReportOnly); +} + +/* +Name: CspReportOnlyEmpty +Description: Tests parsing configuration file with empty content-security-policy-report-only element +Expected: Element should be parsed correctly. +*/ +RUNNER_TEST(CspReportOnlyEmpty) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + parser.Parse(miscWidgetsStuff + "configs/CspReportOnlyEmpty.xml", + ElementParserPtr( + new RootParser(widgetConfig, + L"widget"))); + + RUNNER_ASSERT(!widgetConfig.cspPolicy); + RUNNER_ASSERT(!widgetConfig.cspPolicyReportOnly); +} + +/* +Name: MultipleCsp +Description: Tests parsing configuration file with multiple content-security-policy elements +Expected: Element should be parsed correctly. Only values from first element should be stored +*/ +RUNNER_TEST(MultipleCsp) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + parser.Parse(miscWidgetsStuff + "configs/MultipleCsp.xml", + ElementParserPtr( + new RootParser(widgetConfig, + L"widget"))); + + RUNNER_ASSERT(L"testCSP" == *widgetConfig.cspPolicy); +} + +/* +Name: MultipleCsp +Description: Tests parsing configuration file with multiple content-security-policy-report-only elements +Expected: Element should be parsed correctly. Only values from first element should be stored +*/ +RUNNER_TEST(MultipleCspReportOnly) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + parser.Parse(miscWidgetsStuff + "configs/MultipleCspReportOnly.xml", + ElementParserPtr( + new RootParser(widgetConfig, + L"widget"))); + + RUNNER_ASSERT(L"testCSP" == *widgetConfig.cspPolicyReportOnly); +} diff --git a/tests/general/ParsingMetadataTests.cpp b/tests/general/ParsingMetadataTests.cpp new file mode 100644 index 0000000..a3a0818 --- /dev/null +++ b/tests/general/ParsingMetadataTests.cpp @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file ParsingMetadataTests.cpp + * @author Slawomir Pajak (s.pajak@partner.samsung.com) + * @version 1.0 + * @brief metadata element installation tests + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +using namespace InstallerWrapper; + +namespace{ + +template +bool checkException(Function fun) +{ + Try + { + fun(); + } + Catch(Exception){ + return true; + } + return false; +} + +} // namespace + +#define RUNNER_ASSERT_EXCEPTION(exceptionType, function) \ + { \ + RUNNER_ASSERT(checkException([&](){function})); \ + } + + + +//////////////////////////////////////////////////////////////////////////////// + +RUNNER_TEST_GROUP_INIT(ParsingMetadata) + +/* +Name: InstallWidgetWithMetadata +Description: Tests if widget with metadata element is installed correctly +Expected: widget should be installed correctly and metadata info should be stored in manifest file +*/ +RUNNER_TEST(InstallWidgetWithMetadata) +{ + std::string tizenId; + std::string manifestPath = "/opt/share/packages/"; + RUNNER_ASSERT(install(miscWidgetsStuff + "widgets/metadata.wgt", tizenId) == InstallerWrapper::Success); + + RUNNER_ASSERT(WrtUtilFileExists(manifestPath.append(tizenId.substr(0, 10)).append(".xml"))); + ManifestFile mf(manifestPath); + + RUNNER_ASSERT(mf.getValueByXpath("/p:manifest/p:ui-application/p:metadata[1]/@key") == "key1"); + RUNNER_ASSERT(mf.getValueByXpath("/p:manifest/p:ui-application/p:metadata[2]/@key") == "key2"); + RUNNER_ASSERT(mf.getValueByXpath("/p:manifest/p:ui-application/p:metadata[2]/@value") == "value2"); + RUNNER_ASSERT(mf.getValueByXpath("/p:manifest/p:ui-application/p:metadata[3]/@key") == "key3"); + RUNNER_ASSERT(mf.getValueByXpath("/p:manifest/p:ui-application/p:metadata[3]/@value") == "value3"); + uninstall(tizenId); +} + + +/* +Name: NoMetadata +Description: Tests parsing configuration file without metadata element +Expected: Element should be parsed correctly. +*/ +RUNNER_TEST(NoMetadata) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + parser.Parse(miscWidgetsStuff + "configs/NoMetadata.xml", + ElementParserPtr( + new RootParser(widgetConfig, + L"widget"))); + + RUNNER_ASSERT(widgetConfig.metadataList.empty()); +} + +/* +Name: MetadataEmpty +Description: Tests parsing configuration file with empty metadata element +Expected: Exception should be thrown +*/ +//TODO: Fix in parser needed +//RUNNER_TEST(MetadataEmpty) +//{ +// ParserRunner parser; +// WrtDB::ConfigParserData widgetConfig; +// +// RUNNER_ASSERT_EXCEPTION(ElementParser::Exception::ParseError, +// parser.Parse(miscWidgetsStuff + "configs/MetadataEmpty.xml", +// ElementParserPtr( new RootParser(widgetConfig, L"widget"))); +// ); +//} + +/* +Name: MultipleMetadata +Description: Tests parsing configuration file with multiple metadata element +Expected: Element should be parsed correctly. All values should be stored +*/ +RUNNER_TEST(MultipleMetadata) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + parser.Parse(miscWidgetsStuff + "configs/MultipleMetadata.xml", + ElementParserPtr( + new RootParser(widgetConfig, + L"widget"))); + + RUNNER_ASSERT(3 == widgetConfig.metadataList.size()); + + RUNNER_ASSERT(1 == std::count(widgetConfig.metadataList.begin(), widgetConfig.metadataList.end(), + WrtDB::ConfigParserData::Metadata(DPL::OptionalString(L"key1"), DPL::OptionalString()))); + RUNNER_ASSERT(1 == std::count(widgetConfig.metadataList.begin(), widgetConfig.metadataList.end(), + WrtDB::ConfigParserData::Metadata(DPL::OptionalString(L"key2"), DPL::OptionalString(L"value2")))); + RUNNER_ASSERT(1 == std::count(widgetConfig.metadataList.begin(), widgetConfig.metadataList.end(), + WrtDB::ConfigParserData::Metadata(DPL::OptionalString(L"key3"), DPL::OptionalString(L"value3")))); + +} + +/* +Name: MetadataDuplicatedKey +Description: Tests parsing configuration file with duplicated key attribute value in metadata element +Expected: Exception should be thrown +*/ +//TODO: Fix in parser needed +//RUNNER_TEST(MetadataDuplicatedKey) +//{ +// ParserRunner parser; +// WrtDB::ConfigParserData widgetConfig; +// +// RUNNER_ASSERT_EXCEPTION(ElementParser::Exception::ParseError, +// parser.Parse(miscWidgetsStuff + "configs/MetadataDuplicatedKey.xml", +// ElementParserPtr( new RootParser(widgetConfig, L"widget"))); +// ); +//} diff --git a/tests/general/ParsingSplashImgTests.cpp b/tests/general/ParsingSplashImgTests.cpp new file mode 100644 index 0000000..0e550f7 --- /dev/null +++ b/tests/general/ParsingSplashImgTests.cpp @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file ParsingSplashImgTests.cpp + * @author Slawomir Pajak (s.pajak@partner.samsung.com) + * @version 1.0 + * @brief Splash element installation tests + */ + +#include +#include +#include +#include + +#include +#include +#include + +using namespace InstallerWrapper; + +//////////////////////////////////////////////////////////////////////////////// + +RUNNER_TEST_GROUP_INIT(ParsingSplashImg) + +/* +Name: InstallWidgetWithSplash +Description: Tests if widget with splash is installed correctly +Expected: widget should be installed correctly and splashImg registered in database +*/ +RUNNER_TEST(InstallWidgetWithSplash) +{ + std::string tizenId; + RUNNER_ASSERT(install(miscWidgetsStuff + "widgets/splash.wgt", tizenId) == InstallerWrapper::Success); + + WrtDB::WidgetDAOReadOnly dao(DPL::FromASCIIString(tizenId)); + + RUNNER_ASSERT(*dao.getWidgetInstalledPath() + L"/res/wgt/splash.html" == *dao.getSplashImgSrc()); + + uninstall(tizenId); +} + + +/* +Name: SplashElementOk +Description: Tests parsing correct splash element +Expected: Element should be parsed correcty. +*/ +RUNNER_TEST(SplashElementOk) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + parser.Parse(miscWidgetsStuff + "configs/config_splash1.xml", + ElementParserPtr( + new RootParser(widgetConfig, + L"widget"))); + + RUNNER_ASSERT(DPL::OptionalString(L"splash.html") == widgetConfig.splashImgSrc); +} + +/* +Name: SplashElementEmptySrc +Description: Tests parsing splash element with empty src attribute +Expected: No exception and splash should be null +*/ +RUNNER_TEST(SplashElementEmptySrc) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + parser.Parse(miscWidgetsStuff + "configs/config_splash2.xml", + ElementParserPtr( + new RootParser(widgetConfig, + DPL:: + FromUTF32String( + L"widget")))); + + RUNNER_ASSERT(!widgetConfig.splashImgSrc); +} + +/* +Name: SplashElementNoSrc +Description: Tests parsing splash element with no src attribute +Expected: No exception and splash should be null +*/ +RUNNER_TEST(SplashElementNoSrc) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + parser.Parse(miscWidgetsStuff + "configs/config_splash3.xml", + ElementParserPtr( + new RootParser(widgetConfig, + DPL:: + FromUTF32String( + L"widget")))); + + RUNNER_ASSERT(!widgetConfig.splashImgSrc); + +} + +/* +Name: SplashElementNoNamespace +Description: Tests parsing splash element without tizen namespace +Expected: No exception and splash should be null +*/ +RUNNER_TEST(SplashElementNoNamespace) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + parser.Parse(miscWidgetsStuff + "configs/config_splash4.xml", + ElementParserPtr( + new RootParser(widgetConfig, + DPL:: + FromUTF32String( + L"widget")))); + + RUNNER_ASSERT(!widgetConfig.splashImgSrc); + +} diff --git a/tests/general/ParsingTizenAppcontrolTests.cpp b/tests/general/ParsingTizenAppcontrolTests.cpp new file mode 100644 index 0000000..299354f --- /dev/null +++ b/tests/general/ParsingTizenAppcontrolTests.cpp @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file TestCases.cpp + * @author Karol Pawlowski (k.pawlowski@samsung.com) + * @author Andrzej Surdej (a.surdej@samsung.com) + * @version 1.0 + * @brief Parsing Tizen app-control test's bodies + */ + +#include +#include +#include +#include +#include +#include + +using namespace InstallerWrapper; + +//////////////////////////////////////////////////////////////////////////////// + +RUNNER_TEST_GROUP_INIT(ParsingTizenAppcontrol) + +/* +Name: tizen_app-contro +Description: Tests if widget app-control tag is correctly parsed +Expected: widget should be installed +*/ +RUNNER_TEST(tizen_app_control) +{ + std::string tizenId; + RUNNER_ASSERT(install(miscWidgetsStuff + "widgets/app-control.wgt", + tizenId) == InstallerWrapper::Success); + + WrtDB::WidgetDAOReadOnly dao(DPL::FromASCIIString(tizenId)); + WrtDB::WidgetAppControlList appcontrolList; + dao.getAppControlList(appcontrolList); + uninstall(tizenId); + + _D("Actual size %d", appcontrolList.size()); + RUNNER_ASSERT_MSG(appcontrolList.size() == 4, "Incorrect list size"); + WrtDB::WidgetAppControl s; + s.src = DPL::FromUTF8String("edit1.html"); + s.operation = DPL::FromUTF8String("http://tizen.org/appcontrol/operation/edit"); + s.mime = DPL::FromUTF8String("image/jpg"); /* mime type */ + s.disposition = WrtDB::WidgetAppControl::Disposition::WINDOW; + + RUNNER_ASSERT_MSG( + std::find(appcontrolList.begin(), appcontrolList.end(), s) != appcontrolList.end(), + "Unable to find service #"); + + s.src = DPL::FromUTF8String("edit2.html"); + s.operation = DPL::FromUTF8String("http://tizen.org/appcontrol/operation/view"); + s.mime = DPL::FromUTF8String("audio/ogg"); /* mime type */ + s.disposition = WrtDB::WidgetAppControl::Disposition::WINDOW; + + RUNNER_ASSERT_MSG( + std::find(appcontrolList.begin(), appcontrolList.end(), s) != appcontrolList.end(), + "Unable to find service ##"); + + s.src = DPL::FromUTF8String("edit3.html"); + s.operation = DPL::FromUTF8String("http://tizen.org/appcontrol/operation/call"); + s.mime = DPL::FromUTF8String("image/png"); /* mime type */ + s.disposition = WrtDB::WidgetAppControl::Disposition::WINDOW; + + RUNNER_ASSERT_MSG( + std::find(appcontrolList.begin(), appcontrolList.end(), s) != appcontrolList.end(), + "Unable to find service ###"); + + s.src = DPL::FromUTF8String("edit4.html"); + s.operation = DPL::FromUTF8String("http://tizen.org/appcontrol/operation/send"); + s.mime = DPL::FromUTF8String("text/css"); /* mime type */ + s.disposition = WrtDB::WidgetAppControl::Disposition::WINDOW; + + RUNNER_ASSERT_MSG( + std::find(appcontrolList.begin(), appcontrolList.end(), s) != appcontrolList.end(), + "Unable to find service ####"); +} diff --git a/tests/general/ParsingTizenPrivilegeTests.cpp b/tests/general/ParsingTizenPrivilegeTests.cpp new file mode 100644 index 0000000..1cf2032 --- /dev/null +++ b/tests/general/ParsingTizenPrivilegeTests.cpp @@ -0,0 +1,261 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file ParsingTizenPrivilegeTests.cpp + * @author Slawomir Pajak (s.pajak@partner.samsung.com) + * @version 1.0 + * @brief Parsing Tizen privilege bodies + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +using namespace InstallerWrapper; + +namespace { + +class CompareFeatureByName { +public: + CompareFeatureByName(DPL::String name) : + m_name(name) + { + + } + bool operator()(const WrtDB::DbWidgetFeature& feature) + { + return feature.name == m_name; + } +private: + DPL::String m_name; +}; + +} +//////////////////////////////////////////////////////////////////////////////// + +RUNNER_TEST_GROUP_INIT(ParsingTizenPrivilege) + +/* +Name: tizen_privilege +Description: Tests if widget privilege tag is correctly parsed +Expected: widget should be installed. Privileges and features registered in database +*/ +RUNNER_TEST(InstallWidgetWithPrivilege) +{ + std::string tizenId; + RUNNER_ASSERT(install(miscWidgetsStuff + "widgets/privilege.wgt", tizenId) == InstallerWrapper::Success); + + WrtDB::WidgetDAOReadOnly dao(DPL::FromASCIIString(tizenId)); + WrtDB::PrivilegeList privilegeList = dao.getWidgetPrivilege(); + WrtDB::DbWidgetFeatureSet featureList = dao.getFeaturesList(); + uninstall(tizenId); + + RUNNER_ASSERT(privilegeList.size() == 5); + RUNNER_ASSERT(std::count(privilegeList.begin(), privilegeList.end(), L"http://tizen.org/privilege/location") == 1); + RUNNER_ASSERT( + std::count(privilegeList.begin(), privilegeList.end(), L"http://tizen.org/privilege/notification") == 1); + RUNNER_ASSERT( + std::count(privilegeList.begin(), privilegeList.end(), L"http://tizen.org/privilege/mediacapture") == 1); + RUNNER_ASSERT( + std::count(privilegeList.begin(), privilegeList.end(), L"http://tizen.org/privilege/fullscreen") == 1); + RUNNER_ASSERT( + std::count(privilegeList.begin(), privilegeList.end(), L"http://tizen.org/privilege/unlimitedstorage") == 1); + + RUNNER_ASSERT(featureList.size() == 5); + RUNNER_ASSERT( + std::count_if(featureList.begin(), featureList.end(), CompareFeatureByName(L"http://tizen.org/privilege/location")) == 1); + RUNNER_ASSERT( + std::count_if(featureList.begin(), featureList.end(), CompareFeatureByName(L"http://tizen.org/privilege/notification")) == 1); + RUNNER_ASSERT( + std::count_if(featureList.begin(), featureList.end(), CompareFeatureByName(L"http://tizen.org/privilege/mediacapture")) == 1); + RUNNER_ASSERT( + std::count_if(featureList.begin(), featureList.end(), CompareFeatureByName(L"http://tizen.org/privilege/fullscreen")) == 1); + RUNNER_ASSERT( + std::count_if(featureList.begin(), featureList.end(), CompareFeatureByName(L"http://tizen.org/privilege/unlimitedstorage")) == 1); +} + +/* +Name: PrivilegeElementOk +Description: Tests parsing correct privilege element +Expected: Element should be parsed correcty. +*/ +RUNNER_TEST(PrivilegeElementOk) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + parser.Parse(miscWidgetsStuff + "configs/config_privilege1.xml", + ElementParserPtr(new RootParser(widgetConfig, L"widget"))); + + RUNNER_ASSERT(5 == widgetConfig.privilegeList.size()); + RUNNER_ASSERT( + std::count(widgetConfig.privilegeList.begin(), widgetConfig.privilegeList.end(), + WrtDB::ConfigParserData::Privilege(L"http://tizen.org/privilege/location")) == 1); + RUNNER_ASSERT( + std::count(widgetConfig.privilegeList.begin(), widgetConfig.privilegeList.end(), + WrtDB::ConfigParserData::Privilege(L"http://tizen.org/privilege/notification")) == 1); + RUNNER_ASSERT( + std::count(widgetConfig.privilegeList.begin(), widgetConfig.privilegeList.end(), + WrtDB::ConfigParserData::Privilege(L"http://tizen.org/privilege/mediacapture")) == 1); + RUNNER_ASSERT( + std::count(widgetConfig.privilegeList.begin(), widgetConfig.privilegeList.end(), + WrtDB::ConfigParserData::Privilege(L"http://tizen.org/privilege/fullscreen")) == 1); + RUNNER_ASSERT( + std::count(widgetConfig.privilegeList.begin(), widgetConfig.privilegeList.end(), + WrtDB::ConfigParserData::Privilege(L"http://tizen.org/privilege/unlimitedstorage")) == 1); + + RUNNER_ASSERT(5 == widgetConfig.featuresList.size()); + RUNNER_ASSERT( + std::count(widgetConfig.featuresList.begin(), widgetConfig.featuresList.end(), + WrtDB::ConfigParserData::Feature(L"http://tizen.org/privilege/location")) == 1); + RUNNER_ASSERT( + std::count(widgetConfig.featuresList.begin(), widgetConfig.featuresList.end(), + WrtDB::ConfigParserData::Feature(L"http://tizen.org/privilege/notification")) == 1); + RUNNER_ASSERT( + std::count(widgetConfig.featuresList.begin(), widgetConfig.featuresList.end(), + WrtDB::ConfigParserData::Feature(L"http://tizen.org/privilege/mediacapture")) == 1); + RUNNER_ASSERT( + std::count(widgetConfig.featuresList.begin(), widgetConfig.featuresList.end(), + WrtDB::ConfigParserData::Feature(L"http://tizen.org/privilege/fullscreen")) == 1); + RUNNER_ASSERT( + std::count(widgetConfig.featuresList.begin(), widgetConfig.featuresList.end(), + WrtDB::ConfigParserData::Feature(L"http://tizen.org/privilege/unlimitedstorage")) == 1); +} + +/* +Name: CategoryElementEmptyName +Description: Tests parsing privilege element with empty name attribute +Expected: No exception. PrivilegeList and featuresList should be empty +*/ +RUNNER_TEST(PrivilegeElementEmptyName) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + parser.Parse(miscWidgetsStuff + "configs/config_privilege2.xml", + ElementParserPtr( + new RootParser(widgetConfig, + DPL:: + FromUTF32String( + L"widget")))); + + RUNNER_ASSERT(widgetConfig.privilegeList.empty()); + RUNNER_ASSERT(widgetConfig.featuresList.empty()); +} + +/* +Name: PrivilegeElementNoName +Description: Tests parsing privilege element with no name attribute +Expected: No exception. PrivilegeList and featuresList should be empty +*/ +RUNNER_TEST(PrivilegeElementNoName) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + parser.Parse(miscWidgetsStuff + "configs/config_privilege3.xml", + ElementParserPtr( + new RootParser(widgetConfig, + DPL:: + FromUTF32String( + L"widget")))); + + RUNNER_ASSERT(widgetConfig.categoryList.empty()); + RUNNER_ASSERT(widgetConfig.featuresList.empty()); +} + +/* +Name: PrivilegeElementNoNameSpace +Description: Tests parsing privilege element without proper namespace +Expected: No exception. PrivilegeList and featuresList should be empty +*/ +RUNNER_TEST(PrivilegeElementNoNameSpace) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + parser.Parse(miscWidgetsStuff + "configs/config_privilege4.xml", + ElementParserPtr( + new RootParser(widgetConfig, + DPL:: + FromUTF32String( + L"widget")))); + + RUNNER_ASSERT(widgetConfig.categoryList.empty()); + RUNNER_ASSERT(widgetConfig.featuresList.empty()); +} + +/* +Name: PrivilegeElementDuplicated +Description: Tests parsing three privilege elements (two are identical) +Expected: No exception. PrivilegeList and featuresList should have two distinct elements +*/ +RUNNER_TEST(PrivilegeElementDuplicated) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + parser.Parse(miscWidgetsStuff + "configs/config_privilege5.xml", + ElementParserPtr( + new RootParser(widgetConfig, + DPL:: + FromUTF32String( + L"widget")))); + + RUNNER_ASSERT(2 == widgetConfig.privilegeList.size()); + RUNNER_ASSERT( + std::count(widgetConfig.privilegeList.begin(), widgetConfig.privilegeList.end(), + WrtDB::ConfigParserData::Privilege(L"http://tizen.org/privilege/location")) == 1); + RUNNER_ASSERT( + std::count(widgetConfig.privilegeList.begin(), widgetConfig.privilegeList.end(), + WrtDB::ConfigParserData::Privilege(L"http://tizen.org/privilege/notification")) == 1); + + RUNNER_ASSERT(2 == widgetConfig.featuresList.size()); + RUNNER_ASSERT( + std::count(widgetConfig.featuresList.begin(), widgetConfig.featuresList.end(), + WrtDB::ConfigParserData::Feature(L"http://tizen.org/privilege/location")) == 1); + RUNNER_ASSERT( + std::count(widgetConfig.featuresList.begin(), widgetConfig.featuresList.end(), + WrtDB::ConfigParserData::Feature(L"http://tizen.org/privilege/notification")) == 1); + +} + +/* +Name: PrivilegeElementWrongFormat +Description: Tests parsing privilege elements with wrong format +Expected: No exception. PrivilegeList and featuresList should be empty +*/ +RUNNER_TEST(PrivilegeElementWrongFormat) +{ + ParserRunner parser; + WrtDB::ConfigParserData widgetConfig; + + parser.Parse(miscWidgetsStuff + "configs/config_privilege6.xml", + ElementParserPtr( + new RootParser(widgetConfig, + DPL:: + FromUTF32String( + L"widget")))); + + RUNNER_ASSERT(widgetConfig.privilegeList.empty()); + RUNNER_ASSERT(widgetConfig.featuresList.empty()); +} diff --git a/tests/general/PluginsInstallation.cpp b/tests/general/PluginsInstallation.cpp new file mode 100644 index 0000000..8a779ea --- /dev/null +++ b/tests/general/PluginsInstallation.cpp @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file PluginsInstallation.cpp + * @author Tomasz Iwanek (t.iwanek@samsung.com) + * @version 1.0 + * @brief PluginsInstallation tests implementation + */ + +#include +#include +#include +#include +#include + +//////////////////////////////////////////////////////////////////////////////// + +RUNNER_TEST_GROUP_INIT(PluginsInstallation) + +STATIC_BLOCK +{ + (void)system("wrt_reset_all.sh"); + (void)system("wrt-installer -p"); +} + +#define MAKE_PLUGIN_CHECK_TESTCASE(TESTCASE, LIBNAME) \ + RUNNER_TEST(PluginsInstallation_##TESTCASE) \ + { \ + Try { \ + WrtDB::PluginDAOReadOnly pdao(#LIBNAME); \ + RUNNER_ASSERT_MSG(pdao.getInstallationStatus() == WrtDB::PluginDAOReadOnly::INSTALLATION_COMPLETED, "Plugin is not installed correctly"); \ + } Catch(DPL::Exception) { \ + _E("%s", _rethrown_exception.DumpToString().c_str()); \ + RUNNER_ASSERT_MSG(false, "DPL::Exception"); \ + } \ + } \ + +MAKE_PLUGIN_CHECK_TESTCASE(contact, libwrt-plugins-tizen-contact.so) +MAKE_PLUGIN_CHECK_TESTCASE(systemsetting, libwrt-plugins-tizen-systemsetting.so) +MAKE_PLUGIN_CHECK_TESTCASE(systeminfo, libwrt-plugins-tizen-systeminfo.so) +MAKE_PLUGIN_CHECK_TESTCASE(nfc, libwrt-plugins-tizen-nfc.so) +MAKE_PLUGIN_CHECK_TESTCASE(content, libwrt-plugins-tizen-content.so) +MAKE_PLUGIN_CHECK_TESTCASE(alarm, libwrt-plugins-tizen-alarm.so) +MAKE_PLUGIN_CHECK_TESTCASE(power, libwrt-plugins-tizen-power.so) +MAKE_PLUGIN_CHECK_TESTCASE(secureelement, libwrt-plugins-tizen-secureelement.so) +MAKE_PLUGIN_CHECK_TESTCASE(timeutil, libwrt-plugins-tizen-timeutil.so) +MAKE_PLUGIN_CHECK_TESTCASE(calendar, libwrt-plugins-tizen-calendar.so) +MAKE_PLUGIN_CHECK_TESTCASE(datacontrol, libwrt-plugins-tizen-datacontrol.so) +MAKE_PLUGIN_CHECK_TESTCASE(bookmark, libwrt-plugins-tizen-bookmark.so) +MAKE_PLUGIN_CHECK_TESTCASE(messaging, libwrt-plugins-tizen-messaging.so) +MAKE_PLUGIN_CHECK_TESTCASE(messageport, libwrt-plugins-tizen-messageport.so) +MAKE_PLUGIN_CHECK_TESTCASE(datasync, libwrt-plugins-tizen-datasync.so) +MAKE_PLUGIN_CHECK_TESTCASE(networkbearerselection, libwrt-plugins-tizen-networkbearerselection.so) +MAKE_PLUGIN_CHECK_TESTCASE(package, libwrt-plugins-tizen-package.so) +MAKE_PLUGIN_CHECK_TESTCASE(filesystem, libwrt-plugins-tizen-filesystem.so) +MAKE_PLUGIN_CHECK_TESTCASE(download, libwrt-plugins-tizen-download.so) +MAKE_PLUGIN_CHECK_TESTCASE(application, libwrt-plugins-tizen-application.so) +MAKE_PLUGIN_CHECK_TESTCASE(notification, libwrt-plugins-tizen-notification.so) +MAKE_PLUGIN_CHECK_TESTCASE(push, libwrt-plugins-tizen-push.so) +MAKE_PLUGIN_CHECK_TESTCASE(tizen, libwrt-plugins-tizen-tizen.so) +MAKE_PLUGIN_CHECK_TESTCASE(callhistory, libwrt-plugins-tizen-callhistory.so) +MAKE_PLUGIN_CHECK_TESTCASE(bluetooth, libwrt-plugins-tizen-bluetooth.so) diff --git a/tests/general/TaskConfigurationTests.cpp b/tests/general/TaskConfigurationTests.cpp new file mode 100644 index 0000000..b129e10 --- /dev/null +++ b/tests/general/TaskConfigurationTests.cpp @@ -0,0 +1,645 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file TaskConfigurationTests.cpp + * @author Dominik Duda (d.duda@samsung.com) + * @version 1.0 + * @brief Tests functions from + * wrt-installer/src/jobs/widget_install/task_configuration.cpp + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace Jobs; +using namespace WidgetInstall; + +RUNNER_TEST_GROUP_INIT(TaskConfiguration) + +namespace{ +const std::string wgtTmpPath = "/tmp/J7ZwBudste"; +const std::string wgtPath = InstallerWrapper::miscWidgetsStuff + + "widgets/widgetUpdateVer100Signed.wgt"; +const std::string tarCMD = "tar -xf " + InstallerWrapper::miscWidgetsStuff + + "widgets/widgetInDir.tar -C /tmp"; + +std::string tizenId; + +void staticWrtInitPreloadStatusCallback(std::string tizenId, WrtErrStatus status, + void* userdata) +{ + return; +} +} + +/* +Name: task_configuration_test_01 +Description: Installs widget which is needed for further tests. +This installation will test standard use of the TaskConfiguration class. +Expected: The widget should be successfully installed. +*/ +RUNNER_TEST(task_configuration_test_01) +{ + //Install the widget to get a tizenID + InstallerWrapper::install(wgtPath, tizenId); + + //Uninstall the widget in order to be sure that a next installation + //will be first. + RUNNER_ASSERT_MSG(InstallerWrapper::uninstall(tizenId), + "Failed to uninstall a widget"); + + //That will be the first installation of the widget. + RUNNER_ASSERT_MSG( + InstallerWrapper::install(wgtPath, tizenId) == InstallerWrapper::Success, + "Failed to install a widget"); +} + +/* +Name: task_configuration_test_02 +Description: Tests recognizing an update installation. +Expected: All task configration steps should be completed without errors. +*/ +RUNNER_TEST(task_configuration_test_02) +{ + const WidgetInstallationStruct installerStruct( + InstallerCallbacksTranslate::installFinishedCallback, + InstallerCallbacksTranslate::installProgressCallback, + new InstallerCallbacksTranslate::StatusCallbackStruct( + NULL, &staticWrtInitPreloadStatusCallback, NULL), + InstallMode(), + std::make_shared()); + + InstallerContext i_context; + + i_context.mode = InstallMode(); + i_context.requestedPath = wgtPath; + i_context.job = new Jobs::WidgetInstall::JobWidgetInstall(wgtPath, "", + installerStruct); + + TaskConfiguration taskConf(i_context); + size_t stepsCnt = taskConf.GetStepCount(); + + unsigned int i = 0; + bool result = true; + + while(i < stepsCnt && result) + { + i++; + result = taskConf.NextStep(); + } + + RUNNER_ASSERT(i == stepsCnt); +} + +/* +Name: task_configuration_test_03 +Description: Tests widget installation with incorrect config.xml file. +Expected: Task configuration process should throw an exception when parsing +configuration file. +*/ +RUNNER_TEST(task_configuration_test_03) +{ + const WidgetInstallationStruct installerStruct( + InstallerCallbacksTranslate::installFinishedCallback, + InstallerCallbacksTranslate::installProgressCallback, + new InstallerCallbacksTranslate::StatusCallbackStruct( + NULL, &staticWrtInitPreloadStatusCallback, NULL), + InstallMode(), + std::make_shared()); + + InstallerContext i_context; + + i_context.mode = InstallMode(); + i_context.requestedPath = InstallerWrapper::miscWidgetsStuff + "widgets/widgetFakeConfig.wgt"; + + i_context.job = + new Jobs::WidgetInstall::JobWidgetInstall(wgtPath, "", + installerStruct); + + TaskConfiguration taskConf(i_context); + size_t stepsCnt = taskConf.GetStepCount(); + + unsigned int i = 0; + bool result = true; + + Try{ + while(i < stepsCnt && result) + { + i++; + result = taskConf.NextStep(); + } + } + Catch(WidgetInstall::Exceptions::WidgetConfigFileInvalid){ + RUNNER_ASSERT(i == 4); + return; + } + + RUNNER_ASSERT_MSG(false, + "An Exception should be thrown if config.xml file is incorrect."); +} + +/* +Name: task_configuration_test_04 +Description: Tests task configuration for widget installation directly from +a directory. +Expected: Widget should be successfully installed. +*/ +RUNNER_TEST(task_configuration_test_04) +{ + int ret = system(tarCMD.c_str()); + + RUNNER_ASSERT_MSG(!WIFEXITED(ret) || !WIFSIGNALED(ret), + "Cannot untar a widget to check direct installation from the directory!"); + + const WidgetInstallationStruct installerStruct( + InstallerCallbacksTranslate::installFinishedCallback, + InstallerCallbacksTranslate::installProgressCallback, + new InstallerCallbacksTranslate::StatusCallbackStruct( + NULL, &staticWrtInitPreloadStatusCallback, NULL), + InstallMode(), + std::make_shared()); + + InstallerContext i_context; + + i_context.mode = InstallMode(); + i_context.mode.extension = InstallMode::ExtensionType::DIR; + i_context.requestedPath = wgtTmpPath; + + i_context.job = + new Jobs::WidgetInstall::JobWidgetInstall(wgtPath, "", + installerStruct); + + TaskConfiguration taskConf(i_context); + size_t stepsCnt = taskConf.GetStepCount(); + + unsigned int i = 0; + bool result = true; + + while(i < stepsCnt && result) + { + i++; + result = taskConf.NextStep(); + } + + RUNNER_ASSERT(i == stepsCnt); +} + +/* +Name: task_configuration_test_05 +Description: Tests if an exception will ocure when there is no config.xml file +in the widget directory. +Expected: An exception should be thrown. +*/ +RUNNER_TEST(task_configuration_test_05) +{ + int ret = system(tarCMD.c_str()); + + RUNNER_ASSERT_MSG(!WIFEXITED(ret) || !WIFSIGNALED(ret), + "Cannot untar widget to check direct installation from directory!"); + + const WidgetInstallationStruct installerStruct( + InstallerCallbacksTranslate::installFinishedCallback, + InstallerCallbacksTranslate::installProgressCallback, + new InstallerCallbacksTranslate::StatusCallbackStruct( + NULL, &staticWrtInitPreloadStatusCallback, NULL), + InstallMode(), + std::make_shared()); + + InstallerContext i_context; + + i_context.mode = InstallMode(); + i_context.mode.extension = InstallMode::ExtensionType::DIR; + i_context.requestedPath = wgtTmpPath + "/TestWgt.wgt"; + + i_context.job = + new Jobs::WidgetInstall::JobWidgetInstall(wgtPath, "", + installerStruct); + + TaskConfiguration taskConf(i_context); + size_t stepsCnt = taskConf.GetStepCount(); + + unsigned int i = 0; + bool result = true; + + Try{ + while(i < stepsCnt && result) + { + i++; + + if (i == 3) + { + //Remove config file + RUNNER_ASSERT(WrtUtilRemove(wgtTmpPath + "/config.xml")); + } + + result = taskConf.NextStep(); + } + } + Catch(WrtDB::WidgetDAOReadOnly::Exception::WidgetNotExist){ + RUNNER_ASSERT(i == 3); + return; + } + + RUNNER_ASSERT_MSG(false, + "An Exception should be thrown after deletion of config.xml file."); +} + +/* +Name: task_configuration_test_06 +Description: Tests if missing config file will be detected during parsing step. +Expected: An exception should be thrown if there is no config file. +*/ +RUNNER_TEST(task_configuration_test_06) +{ + int ret = system(tarCMD.c_str()); + + RUNNER_ASSERT_MSG(!WIFEXITED(ret) || !WIFSIGNALED(ret), + "Cannot untar widget to check direct installation from directory!"); + + const WidgetInstallationStruct installerStruct( + InstallerCallbacksTranslate::installFinishedCallback, + InstallerCallbacksTranslate::installProgressCallback, + new InstallerCallbacksTranslate::StatusCallbackStruct( + NULL, &staticWrtInitPreloadStatusCallback, NULL), + InstallMode(), + std::make_shared()); + + InstallerContext i_context; + + i_context.mode = InstallMode(); + i_context.mode.extension = InstallMode::ExtensionType::DIR; + i_context.requestedPath = wgtTmpPath; + + i_context.job = + new Jobs::WidgetInstall::JobWidgetInstall(wgtPath, "", + installerStruct); + + TaskConfiguration taskConf(i_context); + size_t stepsCnt = taskConf.GetStepCount(); + + unsigned int i = 0; + bool result = true; + + Try{ + while(i < stepsCnt && result) + { + i++; + + if (i == 4) + { + //Remove config file + RUNNER_ASSERT(WrtUtilRemove(wgtTmpPath + "/config.xml")); + } + + result = taskConf.NextStep(); + } + } + Catch(WidgetInstall::Exceptions::MissingConfig){ + RUNNER_ASSERT(i == 4); + return; + } + + RUNNER_ASSERT_MSG(false, + "An Exception should be thrown in parsing step if there is no " + "config.xml file in the directory."); +} + +/* +Name: task_configuration_test_07 +Description: Tests reinstallation of a widget from the directory. +Expected: A widget should be successfully installed. +*/ +RUNNER_TEST(task_configuration_test_07) +{ + int ret = system(tarCMD.c_str()); + + RUNNER_ASSERT_MSG(!WIFEXITED(ret) || !WIFSIGNALED(ret), + "Cannot untar widget to check direct installation from directory!"); + + //This widget is needed to be installed to find the tizen PkgId in the database + //during reinstallation step. + RUNNER_ASSERT_MSG( + InstallerWrapper::install(wgtTmpPath + "/TestWgt.wgt", tizenId) == InstallerWrapper::Success, + "Failed to install a widget"); + + const WidgetInstallationStruct installerStruct( + InstallerCallbacksTranslate::installFinishedCallback, + InstallerCallbacksTranslate::installProgressCallback, + new InstallerCallbacksTranslate::StatusCallbackStruct( + NULL, &staticWrtInitPreloadStatusCallback, NULL), + InstallMode(), + std::make_shared()); + + InstallerContext i_context; + + i_context.mode = InstallMode(); + i_context.mode.command = InstallMode::Command::REINSTALL; + i_context.mode.extension = InstallMode::ExtensionType::DIR; + i_context.requestedPath = wgtTmpPath; + + i_context.job = + new Jobs::WidgetInstall::JobWidgetInstall(wgtPath, "", + installerStruct); + + TaskConfiguration taskConf(i_context); + size_t stepsCnt = taskConf.GetStepCount(); + + unsigned int i = 0; + bool result = true; + + while(i < stepsCnt && result) + { + i++; + result = taskConf.NextStep(); + } + + RUNNER_ASSERT(i == stepsCnt); +} + +/* +Name: task_configuration_test_08 +Description: Tests recovery installation of the widget from the directory. +Expected: A widget should be successfully installed. +*/ +RUNNER_TEST(task_configuration_test_08) +{ + int ret = system(tarCMD.c_str()); + + RUNNER_ASSERT_MSG(!WIFEXITED(ret) || !WIFSIGNALED(ret), + "Cannot untar widget to check direct installation from directory!"); + + //This widget is needed to be installed to find the tizen PkgId in the database + //during reinstallation step. + RUNNER_ASSERT_MSG( + InstallerWrapper::install(wgtTmpPath + "/TestWgt.wgt", tizenId) == InstallerWrapper::Success, + "Failed to install a widget"); + + const WidgetInstallationStruct installerStruct( + InstallerCallbacksTranslate::installFinishedCallback, + InstallerCallbacksTranslate::installProgressCallback, + new InstallerCallbacksTranslate::StatusCallbackStruct( + NULL, &staticWrtInitPreloadStatusCallback, NULL), + InstallMode(), + std::make_shared()); + + InstallerContext i_context; + + i_context.mode = InstallMode(); + i_context.mode.command = InstallMode::Command::RECOVERY; + i_context.mode.extension = InstallMode::ExtensionType::DIR; + i_context.requestedPath = wgtTmpPath; + + i_context.job = + new Jobs::WidgetInstall::JobWidgetInstall(wgtPath, "", + installerStruct); + + TaskConfiguration taskConf(i_context); + size_t stepsCnt = taskConf.GetStepCount(); + + unsigned int i = 0; + bool result = true; + + while(i < stepsCnt && result) + { + i++; + result = taskConf.NextStep(); + } + + RUNNER_ASSERT(i == stepsCnt); +} + +/* +Name: task_configuration_test_09 +Description: Tests if a tizenAppID and tizenPkgID will be generated if were not +set earlier. +Expected: IDs should be properly generated. +*/ +RUNNER_TEST(task_configuration_test_09) +{ + const WidgetInstallationStruct installerStruct( + InstallerCallbacksTranslate::installFinishedCallback, + InstallerCallbacksTranslate::installProgressCallback, + new InstallerCallbacksTranslate::StatusCallbackStruct( + NULL, &staticWrtInitPreloadStatusCallback, NULL), + InstallMode(), + std::make_shared()); + + InstallerContext i_context; + + i_context.mode = InstallMode(); + i_context.requestedPath = wgtPath; + + i_context.job = + new Jobs::WidgetInstall::JobWidgetInstall(wgtPath, "", + installerStruct); + + TaskConfiguration taskConf(i_context); + size_t stepsCnt = taskConf.GetStepCount(); + + unsigned int i = 0; + bool result = true; + + while(i < stepsCnt && result) + { + i++; + + if (i == 5){ + i_context.widgetConfig.tzAppid = L""; + i_context.widgetConfig.tzPkgid = L""; + i_context.widgetConfig.configInfo.tizenAppId = boost::none; + i_context.widgetConfig.configInfo.tizenPkgId = boost::none; + } + + result = taskConf.NextStep(); + } + + RUNNER_ASSERT(i == stepsCnt && + i_context.widgetConfig.tzAppid != L"" && + i_context.widgetConfig.tzPkgid != L""); +} + +/* +Name: task_configuration_test_10 +Description: Tests if a tizenPkgID will be generated if was not set earlier. +Expected: ID should be properly generated. +*/ +RUNNER_TEST(task_configuration_test_10) +{ + const WidgetInstallationStruct installerStruct( + InstallerCallbacksTranslate::installFinishedCallback, + InstallerCallbacksTranslate::installProgressCallback, + new InstallerCallbacksTranslate::StatusCallbackStruct( + NULL, &staticWrtInitPreloadStatusCallback, NULL), + InstallMode(), + std::make_shared()); + + InstallerContext i_context; + + i_context.mode = InstallMode(); + i_context.requestedPath = wgtPath; + + i_context.job = + new Jobs::WidgetInstall::JobWidgetInstall(wgtPath, "", + installerStruct); + + TaskConfiguration taskConf(i_context); + size_t stepsCnt = taskConf.GetStepCount(); + + unsigned int i = 0; + bool result = true; + + while(i < stepsCnt && result) + { + i++; + + if (i == 5){ + i_context.widgetConfig.tzPkgid = L""; + i_context.widgetConfig.configInfo.tizenPkgId = boost::none; + } + + result = taskConf.NextStep(); + } + + RUNNER_ASSERT(i == stepsCnt && + i_context.widgetConfig.tzPkgid != L""); +} + +/* +Name: task_configuration_test_11 +Description: Tests if a tizenAppId and tizenPkgID will be generated if +tizenApp ID is too short and tizenPkgID is not set. +Expected: IDs should be properly generated. An exception should be thrown +in step 9 beacuse this widget is already installed. +*/ +RUNNER_TEST(task_configuration_test_11) +{ + const WidgetInstallationStruct installerStruct( + InstallerCallbacksTranslate::installFinishedCallback, + InstallerCallbacksTranslate::installProgressCallback, + new InstallerCallbacksTranslate::StatusCallbackStruct( + NULL, &staticWrtInitPreloadStatusCallback, NULL), + InstallMode(), + std::make_shared()); + + InstallerContext i_context; + + i_context.mode = InstallMode(); + i_context.requestedPath = wgtPath; + + i_context.job = + new Jobs::WidgetInstall::JobWidgetInstall(wgtPath, "", + installerStruct); + + TaskConfiguration taskConf(i_context); + size_t stepsCnt = taskConf.GetStepCount(); + + unsigned int i = 0; + bool result = true; + + Try{ + while(i < stepsCnt && result) + { + i++; + + if (i == 5){ + i_context.widgetConfig.tzPkgid = L""; + i_context.widgetConfig.configInfo.tizenAppId = L"abcd"; + i_context.widgetConfig.configInfo.tizenPkgId = boost::none; + } + + result = taskConf.NextStep(); + } + } + Catch(Jobs::WidgetInstall::Exceptions::WidgetConfigFileInvalid){ + RUNNER_ASSERT(i == 9 && + i_context.widgetConfig.tzPkgid != L""); + return; + } + + RUNNER_ASSERT_MSG(false, "An exception should be thrown because this widget" + " is already installed!"); +} + +/* +Name: task_configuration_test_12 +Description: Tests if a tizenAppId and tizenPkgID will be generated if +tizenApp ID has incorrect characters and tizenPkgID is not set. +Expected: IDs should be properly generated. An exception should be thrown +in step 9 beacuse this widget is already installed. +*/ +RUNNER_TEST(task_configuration_test_12) +{ + const WidgetInstallationStruct installerStruct( + InstallerCallbacksTranslate::installFinishedCallback, + InstallerCallbacksTranslate::installProgressCallback, + new InstallerCallbacksTranslate::StatusCallbackStruct( + NULL, &staticWrtInitPreloadStatusCallback, NULL), + InstallMode(), + std::make_shared()); + + InstallerContext i_context; + + i_context.mode = InstallMode(); + i_context.requestedPath = wgtPath; + + i_context.job = + new Jobs::WidgetInstall::JobWidgetInstall(wgtPath, "", + installerStruct); + + TaskConfiguration taskConf(i_context); + size_t stepsCnt = taskConf.GetStepCount(); + + unsigned int i = 0; + bool result = true; + + Try{ + while(i < stepsCnt && result) + { + i++; + + if (i == 5){ + i_context.widgetConfig.tzPkgid = L""; + i_context.widgetConfig.configInfo.tizenAppId = L"1234!@#$qw"; + i_context.widgetConfig.configInfo.tizenPkgId = boost::none; + + FOREACH(localizedData, i_context.widgetConfig.configInfo.localizedDataSet) + { + localizedData->second.name = L"1234!@#$qw"; + } + } + + result = taskConf.NextStep(); + } + } + Catch(Jobs::WidgetInstall::Exceptions::WidgetConfigFileInvalid){ + RUNNER_ASSERT(i == 9 && + i_context.widgetConfig.tzPkgid != L""); + return; + } + + RUNNER_ASSERT_MSG(false, "An exception should be thrown because this widget" + " is already installed!"); +} diff --git a/tests/general/TestInit.cpp b/tests/general/TestInit.cpp new file mode 100644 index 0000000..5c433ba --- /dev/null +++ b/tests/general/TestInit.cpp @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file TestInit.cpp + * @author Tomasz Iwanek (t.iwanek@samsung.com) + * @version 1.0 + * @brief Main for wrt-installer general tests + */ + +#include +#include +#include +#include + +int main (int argc, char *argv[]) +{ + _D("Starting tests"); + + WrtDB::WrtDatabase::attachToThreadRW(); + //libxml2 initialization + xmlInitParser(); + LIBXML_TEST_VERSION + + int status = + DPL::Test::TestRunnerSingleton::Instance().ExecTestRunner(argc, argv); + xmlCleanupParser(); + WrtDB::WrtDatabase::detachFromThread(); + + return status; +} diff --git a/tests/general/WidgetInstallManifestTests.cpp b/tests/general/WidgetInstallManifestTests.cpp new file mode 100644 index 0000000..2a73cdd --- /dev/null +++ b/tests/general/WidgetInstallManifestTests.cpp @@ -0,0 +1,463 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file WidgetInstallManifestTests.cpp + * @author Dominik Duda (d.duda@samsung.com) + * @version 1.0 + * @brief Tests functions from wrt-installer/src/jobs/widget_install/manifest.cpp + */ +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace Jobs; +using namespace WidgetInstall; + +RUNNER_TEST_GROUP_INIT(WidgetInstallManifest) + +namespace{ + const std::string manifestFilePath("/tmp/manifest.xml"); + Manifest manifest; +} + +/* +Name: wgt_install_manifest_test_01 +Description: Tests creation of an empty manifest file. +Expected: The file should be created. +*/ +RUNNER_TEST(wgt_install_manifest_test_01) +{ + Manifest manifest; + manifest.generate(DPL::FromASCIIString(manifestFilePath)); + + RUNNER_ASSERT(WrtUtilFileExists(manifestFilePath)); +} + +/* +Name: wgt_install_manifest_test_02 +Description: Tests creation of a manifest file with empty icon, label, author +and description nodes. +Expected: All nodes should be successfully created. +*/ +RUNNER_TEST(wgt_install_manifest_test_02) +{ + Manifest manifest; + + manifest.addIcon(IconType()); + manifest.addLabel(LabelType()); + manifest.addAuthor(AuthorType()); + manifest.addDescription(DescriptionType()); + manifest.generate(DPL::FromASCIIString(manifestFilePath)); + + ManifestFile mFile(manifestFilePath); + + RUNNER_ASSERT(mFile.getValueByXpath("/p:manifest/p:icon") == ""); + RUNNER_ASSERT(mFile.getValueByXpath("/p:manifest/p:label") == ""); + RUNNER_ASSERT(mFile.getValueByXpath("/p:manifest/p:author") == ""); + RUNNER_ASSERT(mFile.getValueByXpath("/p:manifest/p:description") == ""); +} + +/* +Name: wgt_install_manifest_test_03 +Description: Tests creation of a manifest file with icon, label, author and +description nodes. +Expected: All nodes should be successfully created. +*/ +RUNNER_TEST(wgt_install_manifest_test_03) +{ + Manifest manifest; + + manifest.addIcon(IconType(L"manifestIcon.png")); + manifest.addLabel(LabelType(L"manifest label")); + manifest.addDescription(DescriptionType(L"manifest description")); + manifest.addDescription(DescriptionType(L"opis manifestu", L"pl-pl")); + manifest.addAuthor(AuthorType( + DPL::String(L"some@email.com"), + DPL::String(L"emailto:some@email.com"), + DPL::String(L"en"), + DPL::String(L"Manifest email"))); + manifest.generate(DPL::FromASCIIString(manifestFilePath)); + + ManifestFile mFile(manifestFilePath); + + RUNNER_ASSERT(mFile.getValueByXpath("/p:manifest/p:icon") + == "manifestIcon.png"); + RUNNER_ASSERT(mFile.getValueByXpath("/p:manifest/p:label") + == "manifest label"); + RUNNER_ASSERT(mFile.getValueByXpath("/p:manifest/p:author/@email") + == "some@email.com"); + RUNNER_ASSERT(mFile.getValueByXpath("/p:manifest/p:author/@href") + == "emailto:some@email.com"); + RUNNER_ASSERT(mFile.getValueByXpath("/p:manifest/p:author/@xml:lang") + == "en"); + RUNNER_ASSERT(mFile.getValueByXpath("/p:manifest/p:author") + == "Manifest email"); + RUNNER_ASSERT(mFile.getValueByXpath("/p:manifest/p:description[1]") + == "manifest description"); + RUNNER_ASSERT(mFile.getValueByXpath("/p:manifest/p:description[2]") + == "opis manifestu"); + RUNNER_ASSERT(mFile.getValueByXpath("/p:manifest/p:description[2]/@xml:lang") + == "pl-pl"); +} + +/* +Name: wgt_install_manifest_test_04 +Description: Tests creation of an account node with a capability node as a child +node of the account-provider node. +Expected: The node should be successfully created with all attributes and child +nodes. +*/ +RUNNER_TEST(wgt_install_manifest_test_04) +{ + Manifest manifest; + Account acc; + AccountProviderType accProv; + std::pair icon; + + accProv.appid = L"id.manifest.xml"; + accProv.multiAccount = L"true"; + + accProv.name.push_back(LabelType()); + accProv.name.push_back(LabelType(L"only name")); + accProv.name.push_back(LabelType(L"name with lang", L"en-gb")); + accProv.name.push_back(LabelType(L"nazwa z lang", L"pl-pl")); + + accProv.capability.push_back(L"Capability_01"); + accProv.capability.push_back(L""); + + icon.first = L"account"; + icon.second = L"/tmp/icon.png"; + accProv.icon.push_back(icon); + + acc.addAccountProvider(accProv); + + manifest.addAccount(acc); + manifest.generate(DPL::FromASCIIString(manifestFilePath)); + + ManifestFile manReader(manifestFilePath); + + RUNNER_ASSERT(manReader.getValueByXpath("/p:manifest/p:account/" + "p:account-provider/@appid") == "id.manifest.xml"); + RUNNER_ASSERT(manReader.getValueByXpath("/p:manifest/p:account/" + "p:account-provider/@multiple-accounts-support") == "true"); + RUNNER_ASSERT(manReader.getValueByXpath("/p:manifest/p:account/" + "p:account-provider/p:icon/@section") == "account"); + RUNNER_ASSERT(manReader.getValueByXpath("/p:manifest/p:account/" + "p:account-provider/p:icon") == "/tmp/icon.png"); + RUNNER_ASSERT(manReader.getValueByXpath("/p:manifest/p:account/" + "p:account-provider/p:label[1]") == ""); + RUNNER_ASSERT(manReader.getValueByXpath("/p:manifest/p:account/" + "p:account-provider/p:label[2]") == "only name"); + RUNNER_ASSERT(manReader.getValueByXpath("/p:manifest/p:account/" + "p:account-provider/p:label[3]") == "name with lang"); + RUNNER_ASSERT(manReader.getValueByXpath("/p:manifest/p:account/" + "p:account-provider/p:label[4]") == "name with lang"); + RUNNER_ASSERT(manReader.getValueByXpath("/p:manifest/p:account/" + "p:account-provider/p:label[4]/@xml:lang") == "en-gb"); + RUNNER_ASSERT(manReader.getValueByXpath("/p:manifest/p:account/" + "p:account-provider/p:label[5]") == "nazwa z lang"); + RUNNER_ASSERT(manReader.getValueByXpath("/p:manifest/p:account/" + "p:account-provider/p:label[5]/@xml:lang") == "pl-pl"); + RUNNER_ASSERT(manReader.getValueByXpath("/p:manifest/p:account/" + "p:account-provider/p:capability[1]") == "Capability_01"); + RUNNER_ASSERT(manReader.getValueByXpath("/p:manifest/p:account/" + "p:account-provider/p:capability[2]") == ""); +} + +/* +Name: wgt_install_manifest_test_05 +Description: Tests creation of a service-application node. +Expected: The node should be successfully created with all attributes and child +nodes. +*/ +RUNNER_TEST(wgt_install_manifest_test_05) +{ + Manifest manifest; + AppControlType appType; + ServiceApplicationType servApp; + + appType.addMime(L"text/plain"); + appType.addUri(L"http://someurl.org"); + appType.addOperation(L"simple operation"); + + servApp.setAppid(L"manifest.id"); + servApp.setAutoRestart(false); + servApp.setExec(L"exec"); + servApp.setOnBoot(false); + servApp.setType(L"someType"); + servApp.addLabel(LabelType(L"simpleLabel")); + servApp.addIcon(IconType(L"simpleIcon.png")); + servApp.addAppControl(appType); + + manifest.addServiceApplication(servApp); + manifest.generate(DPL::FromASCIIString(manifestFilePath)); + + ManifestFile manReader(manifestFilePath); + + RUNNER_ASSERT(manReader.getValueByXpath("/p:manifest/p:service-application/@appid") == "manifest.id"); + RUNNER_ASSERT(manReader.getValueByXpath("/p:manifest/p:service-application/@auto-restart") == "false"); + RUNNER_ASSERT(manReader.getValueByXpath("/p:manifest/p:service-application/@exec") == "exec"); + RUNNER_ASSERT(manReader.getValueByXpath("/p:manifest/p:service-application/@on-boot") == "false"); + RUNNER_ASSERT(manReader.getValueByXpath("/p:manifest/p:service-application/@type") == "someType"); + RUNNER_ASSERT(manReader.getValueByXpath("/p:manifest/p:service-application/p:label") == "simpleLabel"); + RUNNER_ASSERT(manReader.getValueByXpath("/p:manifest/p:service-application/p:icon") == "simpleIcon.png"); + RUNNER_ASSERT(manReader.getValueByXpath("/p:manifest/p:service-application/p:app-control/p:operation/@name") == "simple operation"); + RUNNER_ASSERT(manReader.getValueByXpath("/p:manifest/p:service-application/p:app-control/p:uri/@name") == "http://someurl.org"); + RUNNER_ASSERT(manReader.getValueByXpath("/p:manifest/p:service-application/p:app-control/p:mime/@name") == "text/plain"); +} + +/* +Name: wgt_install_manifest_test_06 +Description: Creats manifest file with an empty ui-application node. +Expected: The empty ui-application node should be created. All node's parameters +should be empty too. +*/ +RUNNER_TEST(wgt_install_manifest_test_06) +{ + Manifest manifest; + UiApplicationType uiApp; + + manifest.addUiApplication(uiApp); + manifest.generate(DPL::FromASCIIString(manifestFilePath)); + + ManifestFile manReader(manifestFilePath); + + Try + { + RUNNER_ASSERT(manReader.getValueByXpath("/p:manifest/p:ui-application") == ""); + RUNNER_ASSERT(manReader.getValueByXpath("/p:manifest/p:ui-application/@appid") == ""); + RUNNER_ASSERT(manReader.getValueByXpath("/p:manifest/p:ui-application/@exec") == ""); + RUNNER_ASSERT(manReader.getValueByXpath("/p:manifest/p:ui-application/@type") == ""); + RUNNER_ASSERT(manReader.getValueByXpath("/p:manifest/p:ui-application/@extraid") == ""); + } + Catch(ManifestFile::ManifestParseError) + { + RUNNER_ASSERT_MSG(false,DPL::Exception::KnownExceptionToString(_rethrown_exception)); + } +} + +/* +Name: wgt_install_manifest_test_07 +Description: Tests creation of an ui-application node. +Expected: The node should be successfully created with all attributes and child +nodes. +*/ +RUNNER_TEST(wgt_install_manifest_test_07) +{ + Manifest manifest; + UiApplicationType uiApp; + + uiApp.setAppid(L"manifest.AppID"); + uiApp.setCategories(L"categories"); + uiApp.setExtraid(L"extraID"); + uiApp.setExec(L"exec"); + uiApp.setMultiple(false); + uiApp.setNodisplay(false); + uiApp.setTaskmanage(true); + uiApp.setType(L"uiType"); + + uiApp.addLabel(LabelType(L"uiLabel")); + uiApp.addIcon(IconType(L"icon.png")); + uiApp.addAppCategory(L"appCategory"); + uiApp.addMetadata(MetadataType(DPL::OptionalString(L"key"), DPL::OptionalString(L"value"))); + + AppControlType appCtrl; + appCtrl.addMime(L"text/plain"); + appCtrl.addOperation(L"appOperation"); + appCtrl.addUri(L"some.uri.com"); + + uiApp.addAppControl(appCtrl); + + manifest.addUiApplication(uiApp); + manifest.generate(DPL::FromASCIIString(manifestFilePath)); + + ManifestFile manReader(manifestFilePath); + + Try + { + RUNNER_ASSERT(manReader.getValueByXpath("/p:manifest/p:ui-application/@appid") == "manifest.AppID"); + RUNNER_ASSERT(manReader.getValueByXpath("/p:manifest/p:ui-application/@exec") == "exec"); + RUNNER_ASSERT(manReader.getValueByXpath("/p:manifest/p:ui-application/@type") == "uiType"); + RUNNER_ASSERT(manReader.getValueByXpath("/p:manifest/p:ui-application/@extraid") == "extraID"); + RUNNER_ASSERT(manReader.getValueByXpath("/p:manifest/p:ui-application/@multiple") == "false"); + RUNNER_ASSERT(manReader.getValueByXpath("/p:manifest/p:ui-application/@nodisplay") == "false"); + RUNNER_ASSERT(manReader.getValueByXpath("/p:manifest/p:ui-application/@taskmanage") == "true"); + RUNNER_ASSERT(manReader.getValueByXpath("/p:manifest/p:ui-application/@categories") == "categories"); + RUNNER_ASSERT(manReader.getValueByXpath("/p:manifest/p:ui-application/p:label") == "uiLabel"); + RUNNER_ASSERT(manReader.getValueByXpath("/p:manifest/p:ui-application/p:icon") == "icon.png"); + RUNNER_ASSERT(manReader.getValueByXpath("/p:manifest/p:ui-application/p:category/@name") == "appCategory"); + RUNNER_ASSERT(manReader.getValueByXpath("/p:manifest/p:ui-application/p:metadata/@key") == "key"); + RUNNER_ASSERT(manReader.getValueByXpath("/p:manifest/p:ui-application/p:metadata/@value") == "value"); + RUNNER_ASSERT(manReader.getValueByXpath("/p:manifest/p:ui-application/p:app-control/p:operation/@name") == "appOperation"); + RUNNER_ASSERT(manReader.getValueByXpath("/p:manifest/p:ui-application/p:app-control/p:uri/@name") == "some.uri.com"); + RUNNER_ASSERT(manReader.getValueByXpath("/p:manifest/p:ui-application/p:app-control/p:mime/@name") == "text/plain"); + } + Catch(ManifestFile::ManifestParseError) + { + RUNNER_ASSERT_MSG(false,DPL::Exception::KnownExceptionToString(_rethrown_exception)); + } +} + +/* +Name: wgt_install_manifest_test_08 +Description: Tests creation of an ime-application node. +Expected: The node should be successfully created with all attributes and child +nodes. +*/ +RUNNER_TEST(wgt_install_manifest_test_08) +{ + Manifest manifest; + ImeApplicationType ime; + + ime.setAppid(L"appID"); + ime.setExec(L"exec"); + ime.setMultiple(true); + ime.setNodisplay(true); + ime.setType(L"type"); + ime.addIcon(IconType(L"imeicon.png")); + ime.addLabel(LabelType(L"imeLabel")); + + manifest.addImeApplication(ime); + manifest.generate(DPL::FromASCIIString(manifestFilePath)); + + ManifestFile manReader(manifestFilePath); + + Try + { + RUNNER_ASSERT(manReader.getValueByXpath("/p:manifest/p:ime-application/@appid") == "appID"); + RUNNER_ASSERT(manReader.getValueByXpath("/p:manifest/p:ime-application/@exec") == "exec"); + RUNNER_ASSERT(manReader.getValueByXpath("/p:manifest/p:ime-application/@multiple") == "true"); + RUNNER_ASSERT(manReader.getValueByXpath("/p:manifest/p:ime-application/@nodisplay") == "true"); + RUNNER_ASSERT(manReader.getValueByXpath("/p:manifest/p:ime-application/@type") == "type"); + RUNNER_ASSERT(manReader.getValueByXpath("/p:manifest/p:ime-application/p:label") == "imeLabel"); + RUNNER_ASSERT(manReader.getValueByXpath("/p:manifest/p:ime-application/p:icon") == "imeicon.png"); + } + Catch(ManifestFile::ManifestParseError) + { + RUNNER_ASSERT_MSG(false,DPL::Exception::KnownExceptionToString(_rethrown_exception)); + } +} + +/* +Name: wgt_install_manifest_test_09 +Description: Tests creation of a livebox node. +Expected: The node should be successfully created with all child nodes. +*/ +RUNNER_TEST(wgt_install_manifest_test_09) +{ + Manifest manifest; + LiveBoxInfo lbox; + BoxInfoType binfo; + BoxSizeType bst; + BoxLabelType blt; + WrtDB::ConfigParserData::LiveboxInfo::BoxSizeInfo bsize; + + lbox.setLiveboxId(L"lboxID"); + lbox.setIcon(L"lboxicon.png"); + lbox.setPrimary(L"lboxprim"); + + + blt.push_back(std::pair(L"pl-pl", L"lbl")); + lbox.setLabel(blt); + + bsize.m_preview = L"true"; + bsize.m_size = L"20;20"; + bsize.m_useDecoration = L"false"; + bst.push_back(bsize); + + binfo.boxMouseEvent = L"onclick"; + binfo.boxSize = bst; + binfo.boxSrc = L"boxSrc"; + binfo.boxTouchEffect = L"false"; + binfo.pdHeight = L"100"; + binfo.pdSrc = L"pdSrc"; + binfo.pdWidth = L"100"; + lbox.setBox(binfo); + + manifest.addLivebox(lbox); + manifest.generate(DPL::FromASCIIString(manifestFilePath)); + + ManifestFile manReader(manifestFilePath); + + Try + { + RUNNER_ASSERT(manReader.getValueByXpath("/p:manifest/p:livebox/@appid") == "lboxID"); + RUNNER_ASSERT(manReader.getValueByXpath("/p:manifest/p:livebox/@primary") == "lboxprim"); + RUNNER_ASSERT(manReader.getValueByXpath("/p:manifest/p:livebox/@abi") == "html"); + RUNNER_ASSERT(manReader.getValueByXpath("/p:manifest/p:livebox/@network") == "true"); + RUNNER_ASSERT(manReader.getValueByXpath("/p:manifest/p:livebox/@nodisplay") == "false"); + RUNNER_ASSERT(manReader.getValueByXpath("/p:manifest/p:livebox/p:label[1]") == "lbl"); + RUNNER_ASSERT(manReader.getValueByXpath("/p:manifest/p:livebox/p:label[1]/@xml:lang") == "pl-pl"); + RUNNER_ASSERT(manReader.getValueByXpath("/p:manifest/p:livebox/p:label[2]") == "NO NAME"); + RUNNER_ASSERT(manReader.getValueByXpath("/p:manifest/p:livebox/p:icon") == "lboxicon.png"); + RUNNER_ASSERT(manReader.getValueByXpath("/p:manifest/p:livebox/p:box/@type") == "buffer"); + RUNNER_ASSERT(manReader.getValueByXpath("/p:manifest/p:livebox/p:box/@mouse_event") == "onclick"); + RUNNER_ASSERT(manReader.getValueByXpath("/p:manifest/p:livebox/p:box/@touch_effect") == "false"); + RUNNER_ASSERT(manReader.getValueByXpath("/p:manifest/p:livebox/p:box/p:size") == "20;20"); + RUNNER_ASSERT(manReader.getValueByXpath("/p:manifest/p:livebox/p:box/p:size/@preview") == "true"); + RUNNER_ASSERT(manReader.getValueByXpath("/p:manifest/p:livebox/p:box/p:size/@need_frame") == "false"); + RUNNER_ASSERT(manReader.getValueByXpath("/p:manifest/p:livebox/p:box/p:script/@src") == "boxSrc"); + RUNNER_ASSERT(manReader.getValueByXpath("/p:manifest/p:livebox/p:pd/@type") == "buffer"); + RUNNER_ASSERT(manReader.getValueByXpath("/p:manifest/p:livebox/p:pd/p:size") == "100x100"); + RUNNER_ASSERT(manReader.getValueByXpath("/p:manifest/p:livebox/p:pd/p:script/@src") == "pdSrc"); + } + Catch(ManifestFile::ManifestParseError) + { + RUNNER_ASSERT_MSG(false,DPL::Exception::KnownExceptionToString(_rethrown_exception)); + } +} + +/* +Name: wgt_install_manifest_test_10 +Description: Tests creation of a privilege node. +Expected: The node should be successfully created. +*/ +RUNNER_TEST(wgt_install_manifest_test_10) +{ + PrivilegeType prv1; + + prv1.addPrivilegeName(L"name_1"); + + manifest.addPrivileges(prv1); + manifest.generate(DPL::FromASCIIString(manifestFilePath)); + + ManifestFile manReader(manifestFilePath); + + Try + { + RUNNER_ASSERT(manReader.getValueByXpath("/p:manifest/p:privileges/p:privilege") == "name_1"); + } + Catch(ManifestFile::ManifestParseError) + { + RUNNER_ASSERT_MSG(false,DPL::Exception::KnownExceptionToString(_rethrown_exception)); + } +} + +/* +Name: wgt_install_manifest_test_11 +Description: Deletes the XML file used for tests. +Expected: The file should be successfully deleted. +*/ +RUNNER_TEST(wgt_install_manifest_test_11) +{ + RUNNER_ASSERT(WrtUtilRemove(manifestFilePath)); +} diff --git a/tests/general/WidgetLocationTests.cpp b/tests/general/WidgetLocationTests.cpp new file mode 100644 index 0000000..f7075de --- /dev/null +++ b/tests/general/WidgetLocationTests.cpp @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + /** + * @file WidgetLocationTests.cpp + * @author Maciej Piotrowski (m.piotrowski@samsung.com) + * @version 1.0 + * @brief WidgetLocation tests + */ + +#include +#include +#include + +RUNNER_TEST_GROUP_INIT(WidgetLocation) + + +/* +Name: WidgetLocationCleanInit +Description: Tests WidgetLocation creation for WidgetLocation::WidgetLocation +*/ +RUNNER_TEST(WidgetLocationCleanInit) +{ + WidgetLocation wl; + + RUNNER_ASSERT(wl.getInstallationDir() == ""); + RUNNER_ASSERT(wl.getPackageInstallationDir() == "/"); + RUNNER_ASSERT(wl.getSourceDir() == "//res/wgt"); + RUNNER_ASSERT(wl.getBinaryDir() == "//bin"); + RUNNER_ASSERT(wl.getUserBinaryDir() == "/opt/usr/apps///bin"); + RUNNER_ASSERT(wl.getExecFile() == "//bin/"); + RUNNER_ASSERT(wl.getBackupDir() == "/.backup"); + RUNNER_ASSERT(wl.getBackupSourceDir() == "/.backup/res/wgt"); + RUNNER_ASSERT(wl.getBackupBinaryDir() == "/.backup/bin"); + RUNNER_ASSERT(wl.getBackupExecFile() == "/.backup/bin/"); + RUNNER_ASSERT(wl.getBackupPrivateDir() == "/.backup/data"); + RUNNER_ASSERT(wl.getUserDataRootDir() == "/opt/usr/apps/"); + RUNNER_ASSERT(wl.getPrivateStorageDir() == "/opt/usr/apps//data"); + RUNNER_ASSERT(wl.getPrivateTempStorageDir() == "/opt/usr/apps//tmp"); + RUNNER_ASSERT(wl.getSharedRootDir() == "/opt/usr/apps//shared"); + RUNNER_ASSERT(wl.getSharedResourceDir() == "/opt/usr/apps//shared/res"); + RUNNER_ASSERT(wl.getSharedDataDir() == "/opt/usr/apps//shared/data"); + RUNNER_ASSERT(wl.getSharedTrustedDir() == "/opt/usr/apps//shared/trusted"); + RUNNER_ASSERT(wl.getBackupSharedDir() == "/.backup/shared"); + RUNNER_ASSERT(wl.getBackupSharedDataDir() == "/.backup/shared/data"); + RUNNER_ASSERT(wl.getBackupSharedTrustedDir() == "/.backup/shared/trusted"); + RUNNER_ASSERT(wl.getNPPluginsDir() == "//res/wgt/plugins"); + RUNNER_ASSERT(wl.getNPPluginsExecFile() == "//bin/.npruntime"); + RUNNER_ASSERT(WrtUtilDirExists(wl.getTemporaryPackageDir())); + RUNNER_ASSERT(wl.getTemporaryRootDir() == "//res/wgt"); + RUNNER_ASSERT(wl.getInstalledIconPath() == ""); + RUNNER_ASSERT(wl.getWidgetSource() == ""); + RUNNER_ASSERT(wl.getPkgId() == DPL::String(L"")); +} + +/* +Name: WidgetLocationPkgIdInit +Description: Tests WidgetLocation creation for WidgetLocation::WidgetLocation wirh pkgid +*/ +RUNNER_TEST(WidgetLocationPkgIdInit) +{ + WidgetLocation wl("1234567890"); + + RUNNER_ASSERT(wl.getInstallationDir() == ""); + RUNNER_ASSERT(wl.getPackageInstallationDir() == "/1234567890"); + RUNNER_ASSERT(wl.getSourceDir() == "/1234567890/res/wgt"); + RUNNER_ASSERT(wl.getBinaryDir() == "/1234567890/bin"); + RUNNER_ASSERT(wl.getUserBinaryDir() == "/opt/usr/apps/1234567890//bin"); + RUNNER_ASSERT(wl.getExecFile() == "/1234567890/bin/"); + RUNNER_ASSERT(wl.getBackupDir() == "/1234567890.backup"); + RUNNER_ASSERT(wl.getBackupSourceDir() == "/1234567890.backup/res/wgt"); + RUNNER_ASSERT(wl.getBackupBinaryDir() == "/1234567890.backup/bin"); + RUNNER_ASSERT(wl.getBackupExecFile() == "/1234567890.backup/bin/"); + RUNNER_ASSERT(wl.getBackupPrivateDir() == "/1234567890.backup/data"); + RUNNER_ASSERT(wl.getUserDataRootDir() == "/opt/usr/apps/1234567890"); + RUNNER_ASSERT(wl.getPrivateStorageDir() == "/opt/usr/apps/1234567890/data"); + RUNNER_ASSERT(wl.getPrivateTempStorageDir() == "/opt/usr/apps/1234567890/tmp"); + RUNNER_ASSERT(wl.getSharedRootDir() == "/opt/usr/apps/1234567890/shared"); + RUNNER_ASSERT(wl.getSharedResourceDir() == "/opt/usr/apps/1234567890/shared/res"); + RUNNER_ASSERT(wl.getSharedDataDir() == "/opt/usr/apps/1234567890/shared/data"); + RUNNER_ASSERT(wl.getSharedTrustedDir() == "/opt/usr/apps/1234567890/shared/trusted"); + RUNNER_ASSERT(wl.getBackupSharedDir() == "/1234567890.backup/shared"); + RUNNER_ASSERT(wl.getBackupSharedDataDir() == "/1234567890.backup/shared/data"); + RUNNER_ASSERT(wl.getBackupSharedTrustedDir() == "/1234567890.backup/shared/trusted"); + RUNNER_ASSERT(wl.getNPPluginsDir() == "/1234567890/res/wgt/plugins"); + RUNNER_ASSERT(wl.getNPPluginsExecFile() == "/1234567890/bin/.npruntime"); + RUNNER_ASSERT(WrtUtilDirExists(wl.getTemporaryPackageDir())); + RUNNER_ASSERT(wl.getTemporaryRootDir() == "/1234567890/res/wgt"); + RUNNER_ASSERT(wl.getInstalledIconPath() == ""); + RUNNER_ASSERT(wl.getWidgetSource() == ""); + RUNNER_ASSERT(wl.getPkgId() == DPL::String(L"1234567890")); +} + +/* +Name: WidgetLocationPkgIdInitAppId +Description: Tests WidgetLocation creation for WidgetLocation::WidgetLocation + with pkgid and appid +*/ +RUNNER_TEST(WidgetLocationPkgIdInitAppId) +{ + WidgetLocation wl("1234567890"); + wl.registerAppid("id123456"); + + RUNNER_ASSERT(wl.getInstallationDir() == ""); + RUNNER_ASSERT(wl.getPackageInstallationDir() == "/1234567890"); + RUNNER_ASSERT(wl.getSourceDir() == "/1234567890/res/wgt"); + RUNNER_ASSERT(wl.getBinaryDir() == "/1234567890/bin"); + RUNNER_ASSERT(wl.getUserBinaryDir() == "/opt/usr/apps/1234567890//bin"); + RUNNER_ASSERT(wl.getExecFile() == "/1234567890/bin/id123456"); + RUNNER_ASSERT(wl.getBackupDir() == "/1234567890.backup"); + RUNNER_ASSERT(wl.getBackupSourceDir() == "/1234567890.backup/res/wgt"); + RUNNER_ASSERT(wl.getBackupBinaryDir() == "/1234567890.backup/bin"); + RUNNER_ASSERT(wl.getBackupExecFile() == "/1234567890.backup/bin/id123456"); + RUNNER_ASSERT(wl.getBackupPrivateDir() == "/1234567890.backup/data"); + RUNNER_ASSERT(wl.getUserDataRootDir() == "/opt/usr/apps/1234567890"); + RUNNER_ASSERT(wl.getPrivateStorageDir() == "/opt/usr/apps/1234567890/data"); + RUNNER_ASSERT(wl.getPrivateTempStorageDir() == "/opt/usr/apps/1234567890/tmp"); + RUNNER_ASSERT(wl.getSharedRootDir() == "/opt/usr/apps/1234567890/shared"); + RUNNER_ASSERT(wl.getSharedResourceDir() == "/opt/usr/apps/1234567890/shared/res"); + RUNNER_ASSERT(wl.getSharedDataDir() == "/opt/usr/apps/1234567890/shared/data"); + RUNNER_ASSERT(wl.getSharedTrustedDir() == "/opt/usr/apps/1234567890/shared/trusted"); + RUNNER_ASSERT(wl.getBackupSharedDir() == "/1234567890.backup/shared"); + RUNNER_ASSERT(wl.getBackupSharedDataDir() == "/1234567890.backup/shared/data"); + RUNNER_ASSERT(wl.getBackupSharedTrustedDir() == "/1234567890.backup/shared/trusted"); + RUNNER_ASSERT(wl.getNPPluginsDir() == "/1234567890/res/wgt/plugins"); + RUNNER_ASSERT(wl.getNPPluginsExecFile() == "/1234567890/bin/id123456.npruntime"); + RUNNER_ASSERT(WrtUtilDirExists(wl.getTemporaryPackageDir())); + RUNNER_ASSERT(wl.getTemporaryRootDir() == "/1234567890/res/wgt"); + RUNNER_ASSERT(wl.getWidgetSource() == ""); + RUNNER_ASSERT(wl.getPkgId() == DPL::String(L"1234567890")); +} + +/* +Name: WidgetLocationExternalLocations +Description: Tests WidgetLocation::listExternalLocations() and WidgetLocation::registerExternalLocation() +*/ +RUNNER_TEST(WidgetLocationExternalLocations) +{ + WidgetLocation wl; + RUNNER_ASSERT(wl.listExternalLocations().size() == 0); + wl.registerExternalLocation("filepath1"); + wl.registerExternalLocation("filepath2"); + wl.registerExternalLocation("filepath3"); + RUNNER_ASSERT(wl.listExternalLocations().size() == 3); + wl.registerExternalLocation("filepath1"); + RUNNER_ASSERT(wl.listExternalLocations().size() == 4); +} + +/* +Name: WidgetLocationAdvancedInit1 +Description: Tests WidgetLocation::WidgetLocation() +*/ +RUNNER_TEST(WidgetLocationAdvancedInit1) +{ + WidgetLocation wl("9876543210", "/opt/usr/apps/9876543210", WrtDB::PKG_TYPE_NOMAL_WEB_APP, false, InstallMode::ExtensionType::DIR); + RUNNER_ASSERT(WrtUtilDirExists(wl.getTemporaryPackageDir())); + RUNNER_ASSERT(wl.getTemporaryRootDir() == "/opt/usr/apps/9876543210/res/wgt"); +} + + +/* +Name: WidgetLocationAdvancedInit2 +Description: Tests WidgetLocation::WidgetLocation() +*/ +RUNNER_TEST(WidgetLocationAdvancedInit2) +{ + WidgetLocation wl("1234567890", "/opt/usr/apps/1234567890/", "/tmp/tempdir/", WrtDB::PKG_TYPE_NOMAL_WEB_APP, false, InstallMode::ExtensionType::WGT); + RUNNER_ASSERT(wl.getTemporaryPackageDir() == "/tmp/tempdir/"); + RUNNER_ASSERT(wl.getTemporaryRootDir() == "/opt/usr/apps/1234567890/res/wgt"); + //fails because there is no use of Jobs::WidgetInstall::createTempPath like it is in constructor + //from WidgetLocationAdvancedInit1 case + //RUNNER_ASSERT(WrtUtilDirExists(wl.getTemporaryPackageDir())); +} diff --git a/tests/general/WidgetUpdateTests.cpp b/tests/general/WidgetUpdateTests.cpp new file mode 100644 index 0000000..064e545 --- /dev/null +++ b/tests/general/WidgetUpdateTests.cpp @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file WidgetUpdateTests.cpp + * @author Grzegorz Rynkowski (g.rynkowski@samsung.com) + * @version 1.0 + * @brief Test a process of updating web applications. + */ + +#include +#include +#include +#include + +using namespace InstallerWrapper; + +#define RUNNER_ASSERT_MSG_SAFE(test, message) \ + { \ + DPL::Test::TestRunnerSingleton::Instance().MarkAssertion(); \ + \ + if (!(test)) \ + { \ + uninstall(tizenId); \ + std::ostringstream assertMsg; \ + assertMsg << message; \ + throw DPL::Test::TestRunner::TestFailed(#test, \ + __FILE__, \ + __LINE__, \ + assertMsg.str()); \ + } \ + } + +RUNNER_TEST_GROUP_INIT(WidgetUpdate) + +/* +Name: validUpdateOfSigned +Description: Tests update the web app where origin and a new one are signed. +Expected: Widget should be successfully installed. +*/ +RUNNER_TEST(validUpdateOfSigned) +{ + std::string tizenId; + std::string wgtPath; + + wgtPath = miscWidgetsStuff + "widgets/widgetUpdateVer100Signed.wgt"; + RUNNER_ASSERT_MSG(install(wgtPath, tizenId) == InstallerWrapper::Success, + "Failed to install widget"); + + wgtPath = miscWidgetsStuff + "widgets/widgetUpdateVer220Signed.wgt"; + RUNNER_ASSERT_MSG_SAFE(install(wgtPath, tizenId) == InstallerWrapper::Success, + "Failed update in case both programs are signed"); + uninstall(tizenId); +} + +/* +Name: validUpdateOfUnsigned +Description: Tests update the web app where origin and a new one are unsigned. +Expected: Widget should be successfully updated. +*/ +RUNNER_TEST(validUpdateOfUnsigned) +{ + std::string tizenId; + std::string wgtPath; + + wgtPath = miscWidgetsStuff + "widgets/widgetUpdateVer100Unsigned.wgt"; + RUNNER_ASSERT_MSG(InstallerWrapper::Success == install(wgtPath, tizenId), + "Failed to install widget"); + + wgtPath = miscWidgetsStuff + "widgets/widgetUpdateVer220Unsigned.wgt"; + RUNNER_ASSERT_MSG_SAFE(InstallerWrapper::Success == install(wgtPath, tizenId), + "Failed update in case both programs are signed"); + uninstall(tizenId); +} + +/* + * Information: + * These tests are incompatible to the specification 2.1 + * (but compatible to the specification 3.0). + */ +///* +//Name: unupdateOfSigned +//Description: Tests update that signed web app could be downgraded. +//Expected: Widget should not be updated. +//*/ +//RUNNER_TEST(unupdateOfSigned) +//{ +// std::string tizenId; +// std::string wgtPath; +// +// wgtPath = miscWidgetsStuff + "widgets/widgetUpdateVer220Signed.wgt"; +// RUNNER_ASSERT_MSG(InstallerWrapper::Success == install(wgtPath, tizenId), +// "Failed to install widget"); +// +// wgtPath = miscWidgetsStuff + "widgets/widgetUpdateVer100Signed.wgt"; +// RUNNER_ASSERT_MSG_SAFE(InstallerWrapper::Success != install(wgtPath, tizenId), +// "Unupdate should be prohibited."); +// uninstall(tizenId); +//} +// +///* +//Name: unupdateOfSigned +//Description: Tests update that unsigned web app could be downgraded. +//Expected: Widget should not be updated. +//*/ +//RUNNER_TEST(unupdateOfUnsigned) +//{ +// std::string tizenId; +// std::string wgtPath; +// +// wgtPath = miscWidgetsStuff + "widgets/widgetUpdateVer220Unsigned.wgt"; +// RUNNER_ASSERT_MSG(InstallerWrapper::Success == install(wgtPath, tizenId), +// "Failed to install widget"); +// +// wgtPath = miscWidgetsStuff + "widgets/widgetUpdateVer100Unsigned.wgt"; +// RUNNER_ASSERT_MSG_SAFE(InstallerWrapper::Success != install(wgtPath, tizenId), +// "Unupdate should be prohibited."); +// uninstall(tizenId); +//} + +/* +Name: validUpdateOfCrossSigned +Description: Tests update the web app where one of widgets are signed and second not. +Expected: Widget should not be updated. +*/ +RUNNER_TEST(updateOfCrossSignedWidgets) +{ + std::string tizenId; + std::string wgtPath; + + { + wgtPath = miscWidgetsStuff + "widgets/widgetUpdateVer100Unsigned.wgt"; + RUNNER_ASSERT_MSG(InstallerWrapper::Success == install(wgtPath, tizenId), + "Failed to install widget"); + + wgtPath = miscWidgetsStuff + "widgets/widgetUpdateVer220Signed.wgt"; + RUNNER_ASSERT_MSG_SAFE(InstallerWrapper::Success != install(wgtPath, tizenId), + "The update unsigned app by the signed app should not be possible"); + uninstall(tizenId); + } + { + wgtPath = miscWidgetsStuff + "widgets/widgetUpdateVer100Signed.wgt"; + RUNNER_ASSERT_MSG(InstallerWrapper::Success == install(wgtPath, tizenId), + "Failed to install widget"); + + wgtPath = miscWidgetsStuff + "widgets/widgetUpdateVer220Unsigned.wgt"; + RUNNER_ASSERT_MSG_SAFE(InstallerWrapper::Success != install(wgtPath, tizenId), + "The update signed app by the unsigned app should not be possible"); + uninstall(tizenId); + } +} + + +/* +Name: updateAnotherAuthor +Description: Tests update the web app by the widget signed by another author. +Expected: Widget should not be updated. +*/ +RUNNER_TEST(updateAnotherAuthor) +{ + std::string tizenId; + std::string wgtPath; + + wgtPath = miscWidgetsStuff + "widgets/widgetUpdateVer100Signed.wgt"; + RUNNER_ASSERT_MSG(InstallerWrapper::Success == install(wgtPath, tizenId), + "Failed to install widget"); + + wgtPath = miscWidgetsStuff + "widgets/widgetUpdateVer220SignedAnotherAuthor.wgt"; + RUNNER_ASSERT_MSG_SAFE(InstallerWrapper::Success != install(wgtPath, tizenId), + "The update by another author should not be possible"); + uninstall(tizenId); +} + + +/* +Name: updateWidgetDataRemember +Description: Tests of keeping app data during widget updating. +Expected: App data should be kept. +*/ +RUNNER_TEST(updateWidgetDataRemember) +{ + std::string tizenId; + std::string wgtPath; + + // Installation of the widget + wgtPath = miscWidgetsStuff + "widgets/widgetUpdateVer100Signed.wgt"; + RUNNER_ASSERT_MSG(install(wgtPath, tizenId) == InstallerWrapper::Success, + "Failed to install widget"); + + // Creating a file + std::string filePath = "/opt/usr/apps/HAdisUJ4Kn/data/test"; + std::string text = "slonce swieci dzisiaj wyjatkowo wysoko"; + std::string command = "echo " + text + " > " + filePath; + system(command.c_str()); + + // Second installation of the widget + wgtPath = miscWidgetsStuff + "widgets/widgetUpdateVer220Signed.wgt"; + RUNNER_ASSERT_MSG_SAFE(InstallerWrapper::Success == install(wgtPath, tizenId), + "Failed update in case both programs are signed"); + + + // Checking of the file created before + std::stringstream ss; + std::ifstream file(filePath); + RUNNER_ASSERT_MSG_SAFE(file.good(), "File is gone"); + + for( std::string line; getline( file, line ); ss << line); + file.close(); + RUNNER_ASSERT_MSG_SAFE(text == ss.str(), "Content of file is not the same"); + uninstall(tizenId); +} diff --git a/tests/general/configs/AllowNavigationEmpty.xml b/tests/general/configs/AllowNavigationEmpty.xml new file mode 100644 index 0000000..720795c --- /dev/null +++ b/tests/general/configs/AllowNavigationEmpty.xml @@ -0,0 +1,6 @@ + + + + test2.org test3.org + + diff --git a/tests/general/configs/AllowNavigationMultipleHosts.xml b/tests/general/configs/AllowNavigationMultipleHosts.xml new file mode 100644 index 0000000..4663bb1 --- /dev/null +++ b/tests/general/configs/AllowNavigationMultipleHosts.xml @@ -0,0 +1,5 @@ + + + http://test2.org test3.org *.test4.org * + + diff --git a/tests/general/configs/AllowNavigationMultipleHostsMultiline.xml b/tests/general/configs/AllowNavigationMultipleHostsMultiline.xml new file mode 100644 index 0000000..d3128c4 --- /dev/null +++ b/tests/general/configs/AllowNavigationMultipleHostsMultiline.xml @@ -0,0 +1,10 @@ + + + + http://test2.org + *.test4.org * + + test3.org + + + diff --git a/tests/general/configs/AppWidgetAutoLaunchEmpty.xml b/tests/general/configs/AppWidgetAutoLaunchEmpty.xml new file mode 100644 index 0000000..5830a27 --- /dev/null +++ b/tests/general/configs/AppWidgetAutoLaunchEmpty.xml @@ -0,0 +1,10 @@ + + + + My DynamicBox + + 1x1 + + + + diff --git a/tests/general/configs/AppWidgetAutoLaunchWrongValue.xml b/tests/general/configs/AppWidgetAutoLaunchWrongValue.xml new file mode 100644 index 0000000..b510ebb --- /dev/null +++ b/tests/general/configs/AppWidgetAutoLaunchWrongValue.xml @@ -0,0 +1,10 @@ + + + + My DynamicBox + + 1x1 + + + + diff --git a/tests/general/configs/AppWidgetFull.xml b/tests/general/configs/AppWidgetFull.xml new file mode 100644 index 0000000..eaa2a0a --- /dev/null +++ b/tests/general/configs/AppWidgetFull.xml @@ -0,0 +1,12 @@ + + + + My DynamicBox + + + 1x1 + + + + + \ No newline at end of file diff --git a/tests/general/configs/AppWidgetIdEmpty.xml b/tests/general/configs/AppWidgetIdEmpty.xml new file mode 100644 index 0000000..ae70c36 --- /dev/null +++ b/tests/general/configs/AppWidgetIdEmpty.xml @@ -0,0 +1,10 @@ + + + + My DynamicBox + + 1x1 + + + + diff --git a/tests/general/configs/AppWidgetIdTooLong.xml b/tests/general/configs/AppWidgetIdTooLong.xml new file mode 100644 index 0000000..eb0066e --- /dev/null +++ b/tests/general/configs/AppWidgetIdTooLong.xml @@ -0,0 +1,10 @@ + + + + My DynamicBox + + 1x1 + + + + diff --git a/tests/general/configs/AppWidgetIdTooShort.xml b/tests/general/configs/AppWidgetIdTooShort.xml new file mode 100644 index 0000000..80a5ed2 --- /dev/null +++ b/tests/general/configs/AppWidgetIdTooShort.xml @@ -0,0 +1,10 @@ + + + + My DynamicBox + + 1x1 + + + + diff --git a/tests/general/configs/AppWidgetIdWrongChar.xml b/tests/general/configs/AppWidgetIdWrongChar.xml new file mode 100644 index 0000000..f132c0f --- /dev/null +++ b/tests/general/configs/AppWidgetIdWrongChar.xml @@ -0,0 +1,10 @@ + + + + My DynamicBox + + 1x1 + + + + diff --git a/tests/general/configs/AppWidgetMinimal.xml b/tests/general/configs/AppWidgetMinimal.xml new file mode 100644 index 0000000..aa7bb26 --- /dev/null +++ b/tests/general/configs/AppWidgetMinimal.xml @@ -0,0 +1,10 @@ + + + + My DynamicBox + + 1x1 + + + + diff --git a/tests/general/configs/AppWidgetMultipleBoxContent.xml b/tests/general/configs/AppWidgetMultipleBoxContent.xml new file mode 100644 index 0000000..619c225 --- /dev/null +++ b/tests/general/configs/AppWidgetMultipleBoxContent.xml @@ -0,0 +1,13 @@ + + + + My DynamicBox + + 1x1 + + + 1x1 + + + + diff --git a/tests/general/configs/AppWidgetMultipleBoxIcon.xml b/tests/general/configs/AppWidgetMultipleBoxIcon.xml new file mode 100644 index 0000000..9b905bf --- /dev/null +++ b/tests/general/configs/AppWidgetMultipleBoxIcon.xml @@ -0,0 +1,12 @@ + + + + My DynamicBox + + + + 1x1 + + + + diff --git a/tests/general/configs/AppWidgetMultipleBoxLabel.xml b/tests/general/configs/AppWidgetMultipleBoxLabel.xml new file mode 100644 index 0000000..c046194 --- /dev/null +++ b/tests/general/configs/AppWidgetMultipleBoxLabel.xml @@ -0,0 +1,12 @@ + + + + test + test_en + test_pl + + 1x1 + + + + diff --git a/tests/general/configs/AppWidgetMultiplePrimary.xml b/tests/general/configs/AppWidgetMultiplePrimary.xml new file mode 100644 index 0000000..365fc19 --- /dev/null +++ b/tests/general/configs/AppWidgetMultiplePrimary.xml @@ -0,0 +1,22 @@ + + + + My DynamicBox + + 1x1 + + + + My DynamicBox + + 1x1 + + + + My DynamicBox + + 1x1 + + + + diff --git a/tests/general/configs/AppWidgetNoBoxContent.xml b/tests/general/configs/AppWidgetNoBoxContent.xml new file mode 100644 index 0000000..8d882f5 --- /dev/null +++ b/tests/general/configs/AppWidgetNoBoxContent.xml @@ -0,0 +1,7 @@ + + + + My DynamicBox + + + diff --git a/tests/general/configs/AppWidgetNoBoxLabel.xml b/tests/general/configs/AppWidgetNoBoxLabel.xml new file mode 100644 index 0000000..8289b97 --- /dev/null +++ b/tests/general/configs/AppWidgetNoBoxLabel.xml @@ -0,0 +1,9 @@ + + + + + 1x1 + + + + diff --git a/tests/general/configs/AppWidgetNoId.xml b/tests/general/configs/AppWidgetNoId.xml new file mode 100644 index 0000000..39b0a32 --- /dev/null +++ b/tests/general/configs/AppWidgetNoId.xml @@ -0,0 +1,10 @@ + + + + My DynamicBox + + 1x1 + + + + diff --git a/tests/general/configs/AppWidgetNoPrimary.xml b/tests/general/configs/AppWidgetNoPrimary.xml new file mode 100644 index 0000000..f501865 --- /dev/null +++ b/tests/general/configs/AppWidgetNoPrimary.xml @@ -0,0 +1,10 @@ + + + + My DynamicBox + + 1x1 + + + + diff --git a/tests/general/configs/AppWidgetPrimaryEmpty.xml b/tests/general/configs/AppWidgetPrimaryEmpty.xml new file mode 100644 index 0000000..acb58ff --- /dev/null +++ b/tests/general/configs/AppWidgetPrimaryEmpty.xml @@ -0,0 +1,10 @@ + + + + My DynamicBox + + 1x1 + + + + diff --git a/tests/general/configs/AppWidgetPrimaryWrongValue.xml b/tests/general/configs/AppWidgetPrimaryWrongValue.xml new file mode 100644 index 0000000..bcb4cdf --- /dev/null +++ b/tests/general/configs/AppWidgetPrimaryWrongValue.xml @@ -0,0 +1,10 @@ + + + + My DynamicBox + + 1x1 + + + + diff --git a/tests/general/configs/AppWidgetUpdatePeriodEmpty.xml b/tests/general/configs/AppWidgetUpdatePeriodEmpty.xml new file mode 100644 index 0000000..2f41ddb --- /dev/null +++ b/tests/general/configs/AppWidgetUpdatePeriodEmpty.xml @@ -0,0 +1,10 @@ + + + + My DynamicBox + + 1x1 + + + + diff --git a/tests/general/configs/AppWidgetUpdatePeriodLow.xml b/tests/general/configs/AppWidgetUpdatePeriodLow.xml new file mode 100644 index 0000000..4c54ab8 --- /dev/null +++ b/tests/general/configs/AppWidgetUpdatePeriodLow.xml @@ -0,0 +1,10 @@ + + + + My DynamicBox + + 1x1 + + + + diff --git a/tests/general/configs/AppWidgetUpdatePeriodWrongFormat.xml b/tests/general/configs/AppWidgetUpdatePeriodWrongFormat.xml new file mode 100644 index 0000000..6cb62f0 --- /dev/null +++ b/tests/general/configs/AppWidgetUpdatePeriodWrongFormat.xml @@ -0,0 +1,10 @@ + + + + My DynamicBox + + 1x1 + + + + diff --git a/tests/general/configs/BoxContentEmpty.xml b/tests/general/configs/BoxContentEmpty.xml new file mode 100644 index 0000000..183ac21 --- /dev/null +++ b/tests/general/configs/BoxContentEmpty.xml @@ -0,0 +1,8 @@ + + + + My DynamicBox + + + + diff --git a/tests/general/configs/BoxContentMouseEventEmpty.xml b/tests/general/configs/BoxContentMouseEventEmpty.xml new file mode 100644 index 0000000..c22f057 --- /dev/null +++ b/tests/general/configs/BoxContentMouseEventEmpty.xml @@ -0,0 +1,10 @@ + + + + My DynamicBox + + 1x1 + + + + diff --git a/tests/general/configs/BoxContentMouseEventWrongValue.xml b/tests/general/configs/BoxContentMouseEventWrongValue.xml new file mode 100644 index 0000000..732ae52 --- /dev/null +++ b/tests/general/configs/BoxContentMouseEventWrongValue.xml @@ -0,0 +1,10 @@ + + + + My DynamicBox + + 1x1 + + + + diff --git a/tests/general/configs/BoxContentMultipleBoxSize.xml b/tests/general/configs/BoxContentMultipleBoxSize.xml new file mode 100644 index 0000000..d5412db --- /dev/null +++ b/tests/general/configs/BoxContentMultipleBoxSize.xml @@ -0,0 +1,12 @@ + + + + My DynamicBox + + 1x1 + 2x1 + 2x2 + + + + diff --git a/tests/general/configs/BoxContentMultiplePd.xml b/tests/general/configs/BoxContentMultiplePd.xml new file mode 100644 index 0000000..66e05e1 --- /dev/null +++ b/tests/general/configs/BoxContentMultiplePd.xml @@ -0,0 +1,12 @@ + + + + My DynamicBox + + 1x1 + + + + + + diff --git a/tests/general/configs/BoxContentNoMouseEvent.xml b/tests/general/configs/BoxContentNoMouseEvent.xml new file mode 100644 index 0000000..aa7bb26 --- /dev/null +++ b/tests/general/configs/BoxContentNoMouseEvent.xml @@ -0,0 +1,10 @@ + + + + My DynamicBox + + 1x1 + + + + diff --git a/tests/general/configs/BoxContentNoSrc.xml b/tests/general/configs/BoxContentNoSrc.xml new file mode 100644 index 0000000..e41081a --- /dev/null +++ b/tests/general/configs/BoxContentNoSrc.xml @@ -0,0 +1,10 @@ + + + + My DynamicBox + + 1x1 + + + + diff --git a/tests/general/configs/BoxContentNoTouchEfect.xml b/tests/general/configs/BoxContentNoTouchEfect.xml new file mode 100644 index 0000000..aa7bb26 --- /dev/null +++ b/tests/general/configs/BoxContentNoTouchEfect.xml @@ -0,0 +1,10 @@ + + + + My DynamicBox + + 1x1 + + + + diff --git a/tests/general/configs/BoxContentSrcEmpty.xml b/tests/general/configs/BoxContentSrcEmpty.xml new file mode 100644 index 0000000..d14c7c7 --- /dev/null +++ b/tests/general/configs/BoxContentSrcEmpty.xml @@ -0,0 +1,10 @@ + + + + My DynamicBox + + 1x1 + + + + diff --git a/tests/general/configs/BoxContentTouchEfectEmpty.xml b/tests/general/configs/BoxContentTouchEfectEmpty.xml new file mode 100644 index 0000000..d62bb8d --- /dev/null +++ b/tests/general/configs/BoxContentTouchEfectEmpty.xml @@ -0,0 +1,10 @@ + + + + My DynamicBox + + 1x1 + + + + diff --git a/tests/general/configs/BoxContentTouchEfectWrongValue.xml b/tests/general/configs/BoxContentTouchEfectWrongValue.xml new file mode 100644 index 0000000..09fed1f --- /dev/null +++ b/tests/general/configs/BoxContentTouchEfectWrongValue.xml @@ -0,0 +1,10 @@ + + + + My DynamicBox + + 1x1 + + + + diff --git a/tests/general/configs/BoxIconEmpty.xml b/tests/general/configs/BoxIconEmpty.xml new file mode 100644 index 0000000..42f3902 --- /dev/null +++ b/tests/general/configs/BoxIconEmpty.xml @@ -0,0 +1,11 @@ + + + + My DynamicBox + + + 1x1 + + + + diff --git a/tests/general/configs/BoxIconSrcEmpty.xml b/tests/general/configs/BoxIconSrcEmpty.xml new file mode 100644 index 0000000..530f2bf --- /dev/null +++ b/tests/general/configs/BoxIconSrcEmpty.xml @@ -0,0 +1,11 @@ + + + + My DynamicBox + + + 1x1 + + + + diff --git a/tests/general/configs/BoxLabelEmpty.xml b/tests/general/configs/BoxLabelEmpty.xml new file mode 100644 index 0000000..72e1c3b --- /dev/null +++ b/tests/general/configs/BoxLabelEmpty.xml @@ -0,0 +1,10 @@ + + + + + + 1x1 + + + + diff --git a/tests/general/configs/BoxSizeEmpty.xml b/tests/general/configs/BoxSizeEmpty.xml new file mode 100644 index 0000000..a8ac2b1 --- /dev/null +++ b/tests/general/configs/BoxSizeEmpty.xml @@ -0,0 +1,10 @@ + + + + My DynamicBox + + + + + + diff --git a/tests/general/configs/BoxSizeNoUserDecoration.xml b/tests/general/configs/BoxSizeNoUserDecoration.xml new file mode 100644 index 0000000..aa7bb26 --- /dev/null +++ b/tests/general/configs/BoxSizeNoUserDecoration.xml @@ -0,0 +1,10 @@ + + + + My DynamicBox + + 1x1 + + + + diff --git a/tests/general/configs/BoxSizePreviewEmpty.xml b/tests/general/configs/BoxSizePreviewEmpty.xml new file mode 100644 index 0000000..c428737 --- /dev/null +++ b/tests/general/configs/BoxSizePreviewEmpty.xml @@ -0,0 +1,10 @@ + + + + My DynamicBox + + 1x1 + + + + diff --git a/tests/general/configs/BoxSizeUserDecorationEmpty.xml b/tests/general/configs/BoxSizeUserDecorationEmpty.xml new file mode 100644 index 0000000..5faf818 --- /dev/null +++ b/tests/general/configs/BoxSizeUserDecorationEmpty.xml @@ -0,0 +1,10 @@ + + + + My DynamicBox + + 1x1 + + + + diff --git a/tests/general/configs/ContentEmpty.xml b/tests/general/configs/ContentEmpty.xml new file mode 100644 index 0000000..df27d2d --- /dev/null +++ b/tests/general/configs/ContentEmpty.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/tests/general/configs/ContentSrcCorrect.xml b/tests/general/configs/ContentSrcCorrect.xml new file mode 100644 index 0000000..78155b0 --- /dev/null +++ b/tests/general/configs/ContentSrcCorrect.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/tests/general/configs/ContentSrcEmpty.xml b/tests/general/configs/ContentSrcEmpty.xml new file mode 100644 index 0000000..3ac71ef --- /dev/null +++ b/tests/general/configs/ContentSrcEmpty.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/tests/general/configs/CspEmpty.xml b/tests/general/configs/CspEmpty.xml new file mode 100644 index 0000000..a44c568 --- /dev/null +++ b/tests/general/configs/CspEmpty.xml @@ -0,0 +1,6 @@ + + + + anyCSP + + diff --git a/tests/general/configs/CspReportOnlyEmpty.xml b/tests/general/configs/CspReportOnlyEmpty.xml new file mode 100644 index 0000000..a9a50d6 --- /dev/null +++ b/tests/general/configs/CspReportOnlyEmpty.xml @@ -0,0 +1,6 @@ + + + + anyCSP + + diff --git a/tests/general/configs/InstallConfig.xml b/tests/general/configs/InstallConfig.xml new file mode 100644 index 0000000..7ee37d7 --- /dev/null +++ b/tests/general/configs/InstallConfig.xml @@ -0,0 +1,25 @@ + + app-control + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/general/configs/MetadataDuplicatedKey.xml b/tests/general/configs/MetadataDuplicatedKey.xml new file mode 100644 index 0000000..d48e5c2 --- /dev/null +++ b/tests/general/configs/MetadataDuplicatedKey.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/tests/general/configs/MetadataEmpty.xml b/tests/general/configs/MetadataEmpty.xml new file mode 100644 index 0000000..71ba7c3 --- /dev/null +++ b/tests/general/configs/MetadataEmpty.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/tests/general/configs/MultipleAllowNavigation.xml b/tests/general/configs/MultipleAllowNavigation.xml new file mode 100644 index 0000000..97d63a6 --- /dev/null +++ b/tests/general/configs/MultipleAllowNavigation.xml @@ -0,0 +1,6 @@ + + + test1.org + test2.org test3.org + + diff --git a/tests/general/configs/MultipleContentCorrect.xml b/tests/general/configs/MultipleContentCorrect.xml new file mode 100644 index 0000000..f9d5512 --- /dev/null +++ b/tests/general/configs/MultipleContentCorrect.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/tests/general/configs/MultipleContentIncorrect.xml b/tests/general/configs/MultipleContentIncorrect.xml new file mode 100644 index 0000000..a9d45d4 --- /dev/null +++ b/tests/general/configs/MultipleContentIncorrect.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/tests/general/configs/MultipleCsp.xml b/tests/general/configs/MultipleCsp.xml new file mode 100644 index 0000000..6a5a362 --- /dev/null +++ b/tests/general/configs/MultipleCsp.xml @@ -0,0 +1,6 @@ + + + testCSP + anyCSP + + diff --git a/tests/general/configs/MultipleCspReportOnly.xml b/tests/general/configs/MultipleCspReportOnly.xml new file mode 100644 index 0000000..48e5e8f --- /dev/null +++ b/tests/general/configs/MultipleCspReportOnly.xml @@ -0,0 +1,6 @@ + + + testCSP + anyCSP + + diff --git a/tests/general/configs/MultipleMetadata.xml b/tests/general/configs/MultipleMetadata.xml new file mode 100644 index 0000000..25fa227 --- /dev/null +++ b/tests/general/configs/MultipleMetadata.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/tests/general/configs/NoAllowNavigation.xml b/tests/general/configs/NoAllowNavigation.xml new file mode 100644 index 0000000..a6b2b12 --- /dev/null +++ b/tests/general/configs/NoAllowNavigation.xml @@ -0,0 +1,4 @@ + + + + diff --git a/tests/general/configs/NoContent.xml b/tests/general/configs/NoContent.xml new file mode 100644 index 0000000..4bb8e41 --- /dev/null +++ b/tests/general/configs/NoContent.xml @@ -0,0 +1,4 @@ + + + + diff --git a/tests/general/configs/NoCsp.xml b/tests/general/configs/NoCsp.xml new file mode 100644 index 0000000..a6b2b12 --- /dev/null +++ b/tests/general/configs/NoCsp.xml @@ -0,0 +1,4 @@ + + + + diff --git a/tests/general/configs/NoMetadata.xml b/tests/general/configs/NoMetadata.xml new file mode 100644 index 0000000..afab039 --- /dev/null +++ b/tests/general/configs/NoMetadata.xml @@ -0,0 +1,4 @@ + + + + diff --git a/tests/general/configs/PdHeightEmpty.xml b/tests/general/configs/PdHeightEmpty.xml new file mode 100644 index 0000000..f92cfb9 --- /dev/null +++ b/tests/general/configs/PdHeightEmpty.xml @@ -0,0 +1,11 @@ + + + + My DynamicBox + + 1x1 + + + + + diff --git a/tests/general/configs/PdHeightExcessive.xml b/tests/general/configs/PdHeightExcessive.xml new file mode 100644 index 0000000..825a64d --- /dev/null +++ b/tests/general/configs/PdHeightExcessive.xml @@ -0,0 +1,11 @@ + + + + My DynamicBox + + 1x1 + + + + + diff --git a/tests/general/configs/PdHeightTooLow.xml b/tests/general/configs/PdHeightTooLow.xml new file mode 100644 index 0000000..aec51bc --- /dev/null +++ b/tests/general/configs/PdHeightTooLow.xml @@ -0,0 +1,11 @@ + + + + My DynamicBox + + 1x1 + + + + + diff --git a/tests/general/configs/PdHeightWrongValue.xml b/tests/general/configs/PdHeightWrongValue.xml new file mode 100644 index 0000000..8ed5704 --- /dev/null +++ b/tests/general/configs/PdHeightWrongValue.xml @@ -0,0 +1,11 @@ + + + + My DynamicBox + + 1x1 + + + + + diff --git a/tests/general/configs/PdNoHeight.xml b/tests/general/configs/PdNoHeight.xml new file mode 100644 index 0000000..d90afdf --- /dev/null +++ b/tests/general/configs/PdNoHeight.xml @@ -0,0 +1,11 @@ + + + + My DynamicBox + + 1x1 + + + + + diff --git a/tests/general/configs/PdNoSrc.xml b/tests/general/configs/PdNoSrc.xml new file mode 100644 index 0000000..f1e6490 --- /dev/null +++ b/tests/general/configs/PdNoSrc.xml @@ -0,0 +1,11 @@ + + + + My DynamicBox + + 1x1 + + + + + diff --git a/tests/general/configs/PdNoWidth.xml b/tests/general/configs/PdNoWidth.xml new file mode 100644 index 0000000..f6112a7 --- /dev/null +++ b/tests/general/configs/PdNoWidth.xml @@ -0,0 +1,11 @@ + + + + My DynamicBox + + 1x1 + + + + + diff --git a/tests/general/configs/PdSrcEmpty.xml b/tests/general/configs/PdSrcEmpty.xml new file mode 100644 index 0000000..af95f32 --- /dev/null +++ b/tests/general/configs/PdSrcEmpty.xml @@ -0,0 +1,11 @@ + + + + My DynamicBox + + 1x1 + + + + + diff --git a/tests/general/configs/PdWidthEmpty.xml b/tests/general/configs/PdWidthEmpty.xml new file mode 100644 index 0000000..284daed --- /dev/null +++ b/tests/general/configs/PdWidthEmpty.xml @@ -0,0 +1,11 @@ + + + + My DynamicBox + + 1x1 + + + + + diff --git a/tests/general/configs/PdWidthNegative.xml b/tests/general/configs/PdWidthNegative.xml new file mode 100644 index 0000000..9699465 --- /dev/null +++ b/tests/general/configs/PdWidthNegative.xml @@ -0,0 +1,11 @@ + + + + My DynamicBox + + 1x1 + + + + + diff --git a/tests/general/configs/PdWidthWrongValue.xml b/tests/general/configs/PdWidthWrongValue.xml new file mode 100644 index 0000000..7b31656 --- /dev/null +++ b/tests/general/configs/PdWidthWrongValue.xml @@ -0,0 +1,11 @@ + + + + My DynamicBox + + 1x1 + + + + + diff --git a/tests/general/configs/PdWidthZero.xml b/tests/general/configs/PdWidthZero.xml new file mode 100644 index 0000000..90e3711 --- /dev/null +++ b/tests/general/configs/PdWidthZero.xml @@ -0,0 +1,11 @@ + + + + My DynamicBox + + 1x1 + + + + + diff --git a/tests/general/configs/config_category1.xml b/tests/general/configs/config_category1.xml new file mode 100644 index 0000000..5f9d631 --- /dev/null +++ b/tests/general/configs/config_category1.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/tests/general/configs/config_category2.xml b/tests/general/configs/config_category2.xml new file mode 100644 index 0000000..45afbd7 --- /dev/null +++ b/tests/general/configs/config_category2.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/tests/general/configs/config_category3.xml b/tests/general/configs/config_category3.xml new file mode 100644 index 0000000..4f33bb9 --- /dev/null +++ b/tests/general/configs/config_category3.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/tests/general/configs/config_category4.xml b/tests/general/configs/config_category4.xml new file mode 100644 index 0000000..46c1c0c --- /dev/null +++ b/tests/general/configs/config_category4.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/tests/general/configs/config_privilege1.xml b/tests/general/configs/config_privilege1.xml new file mode 100644 index 0000000..b97e685 --- /dev/null +++ b/tests/general/configs/config_privilege1.xml @@ -0,0 +1,12 @@ + + + privilege + + + + + + + + + diff --git a/tests/general/configs/config_privilege2.xml b/tests/general/configs/config_privilege2.xml new file mode 100644 index 0000000..64491af --- /dev/null +++ b/tests/general/configs/config_privilege2.xml @@ -0,0 +1,8 @@ + + + privilege + + + + + diff --git a/tests/general/configs/config_privilege3.xml b/tests/general/configs/config_privilege3.xml new file mode 100644 index 0000000..48dcf6f --- /dev/null +++ b/tests/general/configs/config_privilege3.xml @@ -0,0 +1,8 @@ + + + privilege + + + + + diff --git a/tests/general/configs/config_privilege4.xml b/tests/general/configs/config_privilege4.xml new file mode 100644 index 0000000..0578160 --- /dev/null +++ b/tests/general/configs/config_privilege4.xml @@ -0,0 +1,8 @@ + + + privilege + + + + + diff --git a/tests/general/configs/config_privilege5.xml b/tests/general/configs/config_privilege5.xml new file mode 100644 index 0000000..4869c0b --- /dev/null +++ b/tests/general/configs/config_privilege5.xml @@ -0,0 +1,10 @@ + + + privilege + + + + + + + diff --git a/tests/general/configs/config_privilege6.xml b/tests/general/configs/config_privilege6.xml new file mode 100644 index 0000000..791e674 --- /dev/null +++ b/tests/general/configs/config_privilege6.xml @@ -0,0 +1,10 @@ + + + privilege + + + + + + + diff --git a/tests/general/configs/config_splash1.xml b/tests/general/configs/config_splash1.xml new file mode 100644 index 0000000..8604428 --- /dev/null +++ b/tests/general/configs/config_splash1.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/tests/general/configs/config_splash2.xml b/tests/general/configs/config_splash2.xml new file mode 100644 index 0000000..2a5653a --- /dev/null +++ b/tests/general/configs/config_splash2.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/tests/general/configs/config_splash3.xml b/tests/general/configs/config_splash3.xml new file mode 100644 index 0000000..7bc68cb --- /dev/null +++ b/tests/general/configs/config_splash3.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/tests/general/configs/config_splash4.xml b/tests/general/configs/config_splash4.xml new file mode 100644 index 0000000..c7682dc --- /dev/null +++ b/tests/general/configs/config_splash4.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/tests/general/widgets/account.wgt b/tests/general/widgets/account.wgt new file mode 100644 index 0000000..9d3592a Binary files /dev/null and b/tests/general/widgets/account.wgt differ diff --git a/tests/general/widgets/allowNavigation.wgt b/tests/general/widgets/allowNavigation.wgt new file mode 100644 index 0000000..1ed6064 Binary files /dev/null and b/tests/general/widgets/allowNavigation.wgt differ diff --git a/tests/general/widgets/app-control.wgt b/tests/general/widgets/app-control.wgt new file mode 100644 index 0000000..cc98093 Binary files /dev/null and b/tests/general/widgets/app-control.wgt differ diff --git a/tests/general/widgets/appWidgetFull.wgt b/tests/general/widgets/appWidgetFull.wgt new file mode 100644 index 0000000..b228a23 Binary files /dev/null and b/tests/general/widgets/appWidgetFull.wgt differ diff --git a/tests/general/widgets/appWidgetIncorrect.wgt b/tests/general/widgets/appWidgetIncorrect.wgt new file mode 100644 index 0000000..5396411 Binary files /dev/null and b/tests/general/widgets/appWidgetIncorrect.wgt differ diff --git a/tests/general/widgets/appWidgetMinimal.wgt b/tests/general/widgets/appWidgetMinimal.wgt new file mode 100644 index 0000000..2a7aa5d Binary files /dev/null and b/tests/general/widgets/appWidgetMinimal.wgt differ diff --git a/tests/general/widgets/bg-00-with_bg.wgt b/tests/general/widgets/bg-00-with_bg.wgt new file mode 100644 index 0000000..517a3e9 Binary files /dev/null and b/tests/general/widgets/bg-00-with_bg.wgt differ diff --git a/tests/general/widgets/bg-01-missing_file.wgt b/tests/general/widgets/bg-01-missing_file.wgt new file mode 100644 index 0000000..b14d665 Binary files /dev/null and b/tests/general/widgets/bg-01-missing_file.wgt differ diff --git a/tests/general/widgets/bg-02-without_bg.wgt b/tests/general/widgets/bg-02-without_bg.wgt new file mode 100644 index 0000000..ef45c95 Binary files /dev/null and b/tests/general/widgets/bg-02-without_bg.wgt differ diff --git a/tests/general/widgets/category.wgt b/tests/general/widgets/category.wgt new file mode 100644 index 0000000..abb0387 Binary files /dev/null and b/tests/general/widgets/category.wgt differ diff --git a/tests/general/widgets/contentCorrect.wgt b/tests/general/widgets/contentCorrect.wgt new file mode 100644 index 0000000..dd68ae2 Binary files /dev/null and b/tests/general/widgets/contentCorrect.wgt differ diff --git a/tests/general/widgets/contentIncorrect.wgt b/tests/general/widgets/contentIncorrect.wgt new file mode 100644 index 0000000..a0a7e07 Binary files /dev/null and b/tests/general/widgets/contentIncorrect.wgt differ diff --git a/tests/general/widgets/csp.wgt b/tests/general/widgets/csp.wgt new file mode 100644 index 0000000..10a7d2e Binary files /dev/null and b/tests/general/widgets/csp.wgt differ diff --git a/tests/general/widgets/inst_nplug_1.wgt b/tests/general/widgets/inst_nplug_1.wgt new file mode 100644 index 0000000..8447f91 Binary files /dev/null and b/tests/general/widgets/inst_nplug_1.wgt differ diff --git a/tests/general/widgets/inst_nplug_2.wgt b/tests/general/widgets/inst_nplug_2.wgt new file mode 100644 index 0000000..6bb6cff Binary files /dev/null and b/tests/general/widgets/inst_nplug_2.wgt differ diff --git a/tests/general/widgets/inst_nplug_3.wgt b/tests/general/widgets/inst_nplug_3.wgt new file mode 100644 index 0000000..4b30743 Binary files /dev/null and b/tests/general/widgets/inst_nplug_3.wgt differ diff --git a/tests/general/widgets/inst_nplug_4.wgt b/tests/general/widgets/inst_nplug_4.wgt new file mode 100644 index 0000000..a5ddecb Binary files /dev/null and b/tests/general/widgets/inst_nplug_4.wgt differ diff --git a/tests/general/widgets/manifest.wgt b/tests/general/widgets/manifest.wgt new file mode 100644 index 0000000..874f044 Binary files /dev/null and b/tests/general/widgets/manifest.wgt differ diff --git a/tests/general/widgets/metadata.wgt b/tests/general/widgets/metadata.wgt new file mode 100644 index 0000000..b98f17d Binary files /dev/null and b/tests/general/widgets/metadata.wgt differ diff --git a/tests/general/widgets/privilege.wgt b/tests/general/widgets/privilege.wgt new file mode 100644 index 0000000..5bb5f9a Binary files /dev/null and b/tests/general/widgets/privilege.wgt differ diff --git a/tests/general/widgets/splash.wgt b/tests/general/widgets/splash.wgt new file mode 100644 index 0000000..79dcd49 Binary files /dev/null and b/tests/general/widgets/splash.wgt differ diff --git a/tests/general/widgets/widgetFakeConfig.wgt b/tests/general/widgets/widgetFakeConfig.wgt new file mode 100644 index 0000000..6d7af05 Binary files /dev/null and b/tests/general/widgets/widgetFakeConfig.wgt differ diff --git a/tests/general/widgets/widgetInDir.tar b/tests/general/widgets/widgetInDir.tar new file mode 100644 index 0000000..bf0830a Binary files /dev/null and b/tests/general/widgets/widgetInDir.tar differ diff --git a/tests/general/widgets/widgetUpdateVer100Signed.wgt b/tests/general/widgets/widgetUpdateVer100Signed.wgt new file mode 100644 index 0000000..b3ff8bf Binary files /dev/null and b/tests/general/widgets/widgetUpdateVer100Signed.wgt differ diff --git a/tests/general/widgets/widgetUpdateVer100Unsigned.wgt b/tests/general/widgets/widgetUpdateVer100Unsigned.wgt new file mode 100644 index 0000000..751aed0 Binary files /dev/null and b/tests/general/widgets/widgetUpdateVer100Unsigned.wgt differ diff --git a/tests/general/widgets/widgetUpdateVer220Signed.wgt b/tests/general/widgets/widgetUpdateVer220Signed.wgt new file mode 100644 index 0000000..5ef42af Binary files /dev/null and b/tests/general/widgets/widgetUpdateVer220Signed.wgt differ diff --git a/tests/general/widgets/widgetUpdateVer220SignedAnotherAuthor.wgt b/tests/general/widgets/widgetUpdateVer220SignedAnotherAuthor.wgt new file mode 100644 index 0000000..c1aeaa3 Binary files /dev/null and b/tests/general/widgets/widgetUpdateVer220SignedAnotherAuthor.wgt differ diff --git a/tests/general/widgets/widgetUpdateVer220Unsigned.wgt b/tests/general/widgets/widgetUpdateVer220Unsigned.wgt new file mode 100644 index 0000000..181447d Binary files /dev/null and b/tests/general/widgets/widgetUpdateVer220Unsigned.wgt differ diff --git a/tests/general/widgets/widgetUpdateVer220UnsignedDifferentId.wgt b/tests/general/widgets/widgetUpdateVer220UnsignedDifferentId.wgt new file mode 100644 index 0000000..8fb6c19 Binary files /dev/null and b/tests/general/widgets/widgetUpdateVer220UnsignedDifferentId.wgt differ diff --git a/uncrustify.cfg b/uncrustify.cfg new file mode 100644 index 0000000..2bf1d96 --- /dev/null +++ b/uncrustify.cfg @@ -0,0 +1,170 @@ +indent_align_string=true +indent_braces=false +indent_braces_no_func=false +indent_brace_parent=false +indent_namespace=false +indent_extern=false +indent_class=true +indent_class_colon=false +indent_else_if=false +indent_func_call_param=false +indent_func_def_param=false +indent_func_proto_param=false +indent_func_class_param=false +indent_func_ctor_var_param=false +indent_template_param=false +indent_func_param_double=false +indent_relative_single_line_comments=false +indent_col1_comment=true +indent_access_spec_body=false +indent_paren_nl=false +indent_comma_paren=false +indent_bool_paren=false +indent_square_nl=false +indent_preserve_sql=false +indent_align_assign=false +sp_balance_nested_parens=false +align_keep_tabs=false +align_with_tabs=false +align_on_tabstop=false +align_number_left=false +align_func_params=false +align_same_func_call_params=false +align_var_def_colon=false +align_var_def_attribute=false +align_var_def_inline=false +align_right_cmt_mix=false +align_on_operator=false +align_mix_var_proto=false +align_single_line_func=false +align_single_line_brace=false +align_nl_cont=false +align_left_shift=true +nl_collapse_empty_body=true +nl_assign_leave_one_liners=false +nl_class_leave_one_liners=false +nl_enum_leave_one_liners=false +nl_getset_leave_one_liners=false +nl_func_leave_one_liners=false +nl_if_leave_one_liners=false +nl_multi_line_cond=true +nl_multi_line_define=false +nl_before_case=false +nl_after_case=false +nl_after_return=false +nl_after_semicolon=true +nl_after_brace_open=false +nl_after_brace_open_cmt=false +nl_after_vbrace_open=false +nl_after_brace_close=false +nl_define_macro=false +nl_squeeze_ifdef=false +nl_ds_struct_enum_cmt=false +nl_ds_struct_enum_close_brace=false +nl_create_if_one_liner=false +nl_create_for_one_liner=false +nl_create_while_one_liner=false +ls_for_split_full=true +ls_func_split_full=true +nl_after_multiline_comment=false +eat_blanks_after_open_brace=true +eat_blanks_before_close_brace=true +mod_pawn_semicolon=false +mod_full_paren_if_bool=false +mod_remove_extra_semicolon=true +mod_sort_import=false +mod_sort_using=false +mod_sort_include=false +mod_move_case_break=false +mod_remove_empty_return=false +cmt_indent_multi=true +cmt_c_group=false +cmt_c_nl_start=false +cmt_c_nl_end=false +cmt_cpp_group=false +cmt_cpp_nl_start=false +cmt_cpp_nl_end=false +cmt_cpp_to_c=false +cmt_star_cont=true +cmt_multi_check_last=true +cmt_insert_before_preproc=false +pp_indent_at_level=false +pp_region_indent_code=false +pp_if_indent_code=false +pp_define_at_level=false +indent_columns=4 +indent_member=4 +indent_access_spec=-2 +code_width=80 +nl_max=2 +nl_before_access_spec=2 +cmt_width=80 +indent_with_tabs=0 +sp_arith=force +sp_assign=force +sp_enum_assign=force +sp_pp_concat=remove +sp_pp_stringify=remove +sp_bool=force +sp_compare=force +sp_paren_brace=force +sp_angle_paren=remove +sp_before_sparen=force +sp_inside_sparen=remove +sp_after_sparen=force +sp_sparen_brace=force +sp_before_semi=remove +sp_after_semi_for_empty=remove +sp_before_square=remove +sp_before_squares=remove +sp_inside_square=remove +sp_after_comma=force +sp_before_comma=remove +sp_after_class_colon=force +sp_before_class_colon=force +sp_before_case_colon=remove +sp_inside_braces=add +sp_inside_fparens=remove +sp_inside_fparen=remove +sp_func_call_paren=remove +sp_func_class_paren=remove +sp_else_brace=force +sp_brace_else=force +sp_catch_brace=force +sp_brace_catch=force +sp_try_brace=force +sp_before_dc=remove +sp_after_dc=remove +sp_not=remove +sp_inv=remove +sp_addr=remove +sp_member=remove +sp_deref=remove +sp_sign=remove +sp_incdec=remove +sp_cond_colon=force +sp_cond_question=force +sp_case_label=force +nl_assign_brace=remove +nl_if_brace=remove +nl_brace_else=remove +nl_elseif_brace=remove +nl_else_brace=remove +nl_else_if=remove +nl_try_brace=remove +nl_for_brace=remove +nl_catch_brace=remove +nl_brace_catch=remove +nl_while_brace=remove +nl_do_brace=remove +nl_brace_while=remove +nl_switch_brace=remove +nl_namespace_brace=remove +nl_class_brace=force +nl_fdef_brace=force +pos_class_comma=trail +pos_class_colon=trail +mod_full_brace_do=add +mod_full_brace_for=add +mod_full_brace_if=add +mod_full_brace_while=add diff --git a/uncrustify.sh b/uncrustify.sh new file mode 100755 index 0000000..49ad3cf --- /dev/null +++ b/uncrustify.sh @@ -0,0 +1 @@ +uncrustify -c uncrustify.cfg --no-backup `find . -regex "\(.*\.cpp\|.*\.h\|.*\.c\|.*\.cc\)" | grep -v "orm.h\|orm_generator.h\|3rdparty\|examples"` diff --git a/wrt-installer.manifest b/wrt-installer.manifest new file mode 100644 index 0000000..eccc16f --- /dev/null +++ b/wrt-installer.manifest @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/wrt-installer.rule b/wrt-installer.rule new file mode 100644 index 0000000..68ce76f --- /dev/null +++ b/wrt-installer.rule @@ -0,0 +1 @@ +wrt-installer aul::terminate x