diff options
248 files changed, 23847 insertions, 0 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100755 index 0000000..f99cd6c --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,91 @@ +# Copyright (c) 2012-13 Samsung Electronics Co., Ltd All Rights Reserved +# +# Licensed under the Flora License, Version 1.1 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://floralicense.org/license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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) + +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +PROJECT(web-provider CXX) + +STRING(REGEX MATCH "([^.]*)" CMAKE_PROJECT_API_VERSION "${CMAKE_PROJECT_VERSION}") +INCLUDE(FindPkgConfig) + +# Build type +IF(NOT CMAKE_BUILD_TYPE) + SET(CMAKE_BUILD_TYPE "Release") +ENDIF(NOT CMAKE_BUILD_TYPE) + +SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") +INCLUDE(OptionsTizen) + +# Compiler flags +SET(CMAKE_C_FLAGS_PROFILING "-O0 -g -pg") +SET(CMAKE_CXX_FLAGS_PROFILING "-O0 -std=c++0x -g -pg") +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(GC_SECTIONS_FLAGS "-fdata-sections -ffunction-sections -Wl,--gc-sections") +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${GC_SECTIONS_FLAGS}") +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${GC_SECTIONS_FLAGS}") + +# Set compiler options +ADD_DEFINITIONS("-Wall") +ADD_DEFINITIONS("-Wextra") +ADD_DEFINITIONS("-fPIC") +ADD_DEFINITIONS("-Wno-deprecated") +ADD_DEFINITIONS("-fvisibility=hidden") +ADD_DEFINITIONS("-shared") + +# Set Tag Name +ADD_DEFINITIONS("-DLOG_TAG=\"${PROJECT_NAME}\"") + +SET(PKGCONFIG_DIR pkgconfig) +SET(DATA_DIR data) + +# Macro for easy usage +MACRO(INSTALL_FILE FILE DEST_DIR) + INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${FILE} + DESTINATION ${DEST_DIR}) +ENDMACRO() +MACRO(INSTALL_FILE_RENAMED FILE DEST_DIR NEW_NAME) + INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${FILE} + DESTINATION ${DEST_DIR} RENAME ${NEW_NAME}) +ENDMACRO() +MACRO(CONFIG_FILE SRC_FILE DEST_FILE) + CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/${SRC_FILE} + ${CMAKE_CURRENT_SOURCE_DIR}/${DEST_FILE} @ONLY) +ENDMACRO() + +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/src) +ADD_SUBDIRECTORY(src) +ADD_SUBDIRECTORY(Po) + +CONFIG_FILE(${PKGCONFIG_DIR}/web-provider-svc.pc.in ${PKGCONFIG_DIR}/web-provider-svc.pc) # DEPRECATED +INSTALL_FILE(${PKGCONFIG_DIR}/web-provider-svc.pc lib/pkgconfig) # DEPRECATED + +CONFIG_FILE(${PKGCONFIG_DIR}/web-provider.pc.in ${PKGCONFIG_DIR}/web-provider.pc) +INSTALL_FILE(${PKGCONFIG_DIR}/web-provider.pc lib/pkgconfig) +INSTALL_FILE(livebox.web-provider.xml /usr/share/packages) +INSTALL_FILE(${DATA_DIR}/web_provider_reset_db.sh bin) +INSTALL_FILE(${DATA_DIR}/web_provider_db.sql /usr/share/${PROJECT_NAME}) +INSTALL_FILE(${DATA_DIR}/200.livebox.web-provider.patch.sh /etc/opt/upgrade) + +IF(DEVICE_PROFILE STREQUAL "wearable") + INSTALL_FILE(livebox.web-provider.rule /etc/smack/accesses2.d) +ELSE(DEVICE_PROFILE STREQUAL "wearable") + INSTALL_FILE(livebox.web-provider.rule /etc/smack/accesses.d) +ENDIF(DEVICE_PROFILE STREQUAL "wearable") + +SET_DIRECTORY_PROPERTIES(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "web-provider-svc.pc") diff --git a/LICENSE.Flora b/LICENSE.Flora new file mode 100755 index 0000000..571fe79 --- /dev/null +++ b/LICENSE.Flora @@ -0,0 +1,206 @@ +Flora License + +Version 1.1, April, 2013 + +http://floralicense.org/license/ + +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. + +"Tizen Certified Platform" shall mean a software platform that complies +with the standards set forth in the Tizen Compliance Specification +and passes the Tizen Compliance Tests as defined from time to time +by the Tizen Technical Steering Group and certified by the Tizen +Association or its designated agent. + +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 +solely as incorporated into a Tizen Certified Platform, 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 solely +as incorporated into a Tizen Certified Platform 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 pursuant to the copyright license +above, in any medium, with or without modifications, and in Source or +Object form, provided that You meet the following conditions: + + 1. You must give any other recipients of the Work or Derivative Works + a copy of this License; and + 2. You must cause any modified files to carry prominent notices stating + that You changed the files; and + 3. 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 + 4. 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 + and your own copyright statement or terms and conditions do not conflict + the conditions stated in the License including section 3. + +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 Flora License to your work + +To apply the Flora 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 Flora License, Version 1.1 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://floralicense.org/license/ + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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/Po/CMakeLists.txt b/Po/CMakeLists.txt new file mode 100755 index 0000000..462c6b3 --- /dev/null +++ b/Po/CMakeLists.txt @@ -0,0 +1,46 @@ +# Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved +# +# Licensed under the Flora License, Version 1.1 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://floralicense.org/license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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 Leerang Song (leerang.song@samsung.com) + +SET(POFILES +hy.po az.po eu.po bg.po ca.po cs.po da.po nl_NL.po en.po en_US.po +et.po fi.po fr_FR.po gl.po hr.po ka.po de_DE.po el_GR.po hu.po is.po +it_IT.po kk.po ko_KR.po lv.po lt.po nb.po pl.po pt_PT.po pt_BR.po ro.po +ru_RU.po sr.po sk.po sl.po es_ES.po es_MX.po sv.po tr_TR.po uk.po uz.po +fr_CA.po ja_JP.po) + +SET(LOCALE_DIR "/usr/share/res/locale/") +ADD_DEFINITIONS("-DLOCALEDIR=\"${LOCALE_DIR}\"") +SET(MSGFMT "/usr/bin/msgfmt") + + FOREACH(pofile ${POFILES}) + SET(pofile ${CMAKE_CURRENT_SOURCE_DIR}/${pofile}) + MESSAGE("PO: ${pofile}") + GET_FILENAME_COMPONENT(absPofile ${pofile} ABSOLUTE) + GET_FILENAME_COMPONENT(lang ${absPofile} NAME_WE) + + SET(moFile ${CMAKE_CURRENT_BINARY_DIR}/${lang}.mo) + ADD_CUSTOM_COMMAND( OUTPUT ${moFile} + COMMAND ${MSGFMT} -o ${moFile} ${absPofile} + DEPENDS ${absPofile} ) + INSTALL(FILES ${moFile} + DESTINATION ${LOCALE_DIR}/${lang}/LC_MESSAGES + RENAME ${PROJECT_NAME}.mo) +SET(moFiles ${moFiles} ${moFile}) +ENDFOREACH(pofile) + +MESSAGE(".mo files: ${moFiles}") +ADD_CUSTOM_TARGET(po ALL DEPENDS ${moFiles}) + diff --git a/Po/ar.po b/Po/ar.po new file mode 100755 index 0000000..dc63866 --- /dev/null +++ b/Po/ar.po @@ -0,0 +1,21 @@ +msgid "IDS_ST_BODY_12_HOURS" +msgstr "12 ساعة" + +msgid "IDS_ST_BUTTON_CANCEL" +msgstr "إلغاء" + +msgid "IDS_BR_OPT_NEVER" +msgstr "مطلقا" + +msgid "IDS_ST_BODY_6_HOURS_TMO" +msgstr "6 ساعات" + +msgid "IDS_ST_BODY_1_HOUR" +msgstr "ساعة واحدة" + +msgid "IDS_ST_BODY_3HOURS" +msgstr "3 ساعات" + +msgid "IDS_BR_HEADER_AUTO_REFRESH" +msgstr "تحديث تلقائي" + diff --git a/Po/az.po b/Po/az.po new file mode 100755 index 0000000..4e47d4e --- /dev/null +++ b/Po/az.po @@ -0,0 +1,21 @@ +msgid "IDS_ST_BODY_12_HOURS" +msgstr "12 saat" + +msgid "IDS_ST_BUTTON_CANCEL" +msgstr "Ləğv et" + +msgid "IDS_BR_OPT_NEVER" +msgstr "Heç vaxt" + +msgid "IDS_ST_BODY_6_HOURS_TMO" +msgstr "6 saat" + +msgid "IDS_ST_BODY_1_HOUR" +msgstr "1 saat" + +msgid "IDS_ST_BODY_3HOURS" +msgstr "3 saat" + +msgid "IDS_BR_HEADER_AUTO_REFRESH" +msgstr "Avtomatik yeniləmə" + diff --git a/Po/bg.po b/Po/bg.po new file mode 100755 index 0000000..e79dad0 --- /dev/null +++ b/Po/bg.po @@ -0,0 +1,21 @@ +msgid "IDS_ST_BODY_12_HOURS" +msgstr "12 часа" + +msgid "IDS_ST_BUTTON_CANCEL" +msgstr "Отказ" + +msgid "IDS_BR_OPT_NEVER" +msgstr "Никога" + +msgid "IDS_ST_BODY_6_HOURS_TMO" +msgstr "6 часа" + +msgid "IDS_ST_BODY_1_HOUR" +msgstr "1 час" + +msgid "IDS_ST_BODY_3HOURS" +msgstr "3 часа" + +msgid "IDS_BR_HEADER_AUTO_REFRESH" +msgstr "Автоматично опресняване" + diff --git a/Po/ca.po b/Po/ca.po new file mode 100755 index 0000000..aac7114 --- /dev/null +++ b/Po/ca.po @@ -0,0 +1,21 @@ +msgid "IDS_ST_BODY_12_HOURS" +msgstr "12 hores" + +msgid "IDS_ST_BUTTON_CANCEL" +msgstr "Cancelar" + +msgid "IDS_BR_OPT_NEVER" +msgstr "Mai" + +msgid "IDS_ST_BODY_6_HOURS_TMO" +msgstr "6 hores" + +msgid "IDS_ST_BODY_1_HOUR" +msgstr "1 hora" + +msgid "IDS_ST_BODY_3HOURS" +msgstr "3 hores" + +msgid "IDS_BR_HEADER_AUTO_REFRESH" +msgstr "Actualitzar automàticament" + diff --git a/Po/cs.po b/Po/cs.po new file mode 100755 index 0000000..571ba99 --- /dev/null +++ b/Po/cs.po @@ -0,0 +1,21 @@ +msgid "IDS_ST_BODY_12_HOURS" +msgstr "12 hodin" + +msgid "IDS_ST_BUTTON_CANCEL" +msgstr "Zrušit" + +msgid "IDS_BR_OPT_NEVER" +msgstr "Nikdy" + +msgid "IDS_ST_BODY_6_HOURS_TMO" +msgstr "6 hodin" + +msgid "IDS_ST_BODY_1_HOUR" +msgstr "1 hodina" + +msgid "IDS_ST_BODY_3HOURS" +msgstr "3 hodiny" + +msgid "IDS_BR_HEADER_AUTO_REFRESH" +msgstr "Automatická aktualizace" + diff --git a/Po/da.po b/Po/da.po new file mode 100755 index 0000000..2de61d2 --- /dev/null +++ b/Po/da.po @@ -0,0 +1,21 @@ +msgid "IDS_ST_BODY_12_HOURS" +msgstr "12 timer" + +msgid "IDS_ST_BUTTON_CANCEL" +msgstr "Annullér" + +msgid "IDS_BR_OPT_NEVER" +msgstr "Aldrig" + +msgid "IDS_ST_BODY_6_HOURS_TMO" +msgstr "6 timer" + +msgid "IDS_ST_BODY_1_HOUR" +msgstr "1 time" + +msgid "IDS_ST_BODY_3HOURS" +msgstr "3 timer" + +msgid "IDS_BR_HEADER_AUTO_REFRESH" +msgstr "Automatisk opdatering" + diff --git a/Po/de_DE.po b/Po/de_DE.po new file mode 100755 index 0000000..1391bcd --- /dev/null +++ b/Po/de_DE.po @@ -0,0 +1,21 @@ +msgid "IDS_ST_BODY_12_HOURS" +msgstr "12 Stunden" + +msgid "IDS_ST_BUTTON_CANCEL" +msgstr "Abbruch" + +msgid "IDS_BR_OPT_NEVER" +msgstr "Nie" + +msgid "IDS_ST_BODY_6_HOURS_TMO" +msgstr "6 Stunden" + +msgid "IDS_ST_BODY_1_HOUR" +msgstr "1 Stunde" + +msgid "IDS_ST_BODY_3HOURS" +msgstr "3 Stunden" + +msgid "IDS_BR_HEADER_AUTO_REFRESH" +msgstr "Autom. Aktualisierung" + diff --git a/Po/el_GR.po b/Po/el_GR.po new file mode 100755 index 0000000..2ae63db --- /dev/null +++ b/Po/el_GR.po @@ -0,0 +1,21 @@ +msgid "IDS_ST_BODY_12_HOURS" +msgstr "12 ώρες" + +msgid "IDS_ST_BUTTON_CANCEL" +msgstr "Ακύρωση" + +msgid "IDS_BR_OPT_NEVER" +msgstr "Ποτέ" + +msgid "IDS_ST_BODY_6_HOURS_TMO" +msgstr "6 ώρες" + +msgid "IDS_ST_BODY_1_HOUR" +msgstr "1 ώρα" + +msgid "IDS_ST_BODY_3HOURS" +msgstr "3 ώρες" + +msgid "IDS_BR_HEADER_AUTO_REFRESH" +msgstr "Αυτόματη ανανέωση" + diff --git a/Po/en.po b/Po/en.po new file mode 100755 index 0000000..d5defb1 --- /dev/null +++ b/Po/en.po @@ -0,0 +1,21 @@ +msgid "IDS_ST_BODY_12_HOURS" +msgstr "12 hours" + +msgid "IDS_ST_BUTTON_CANCEL" +msgstr "Cancel" + +msgid "IDS_BR_OPT_NEVER" +msgstr "Never" + +msgid "IDS_ST_BODY_6_HOURS_TMO" +msgstr "6 hours" + +msgid "IDS_ST_BODY_1_HOUR" +msgstr "1 hour" + +msgid "IDS_ST_BODY_3HOURS" +msgstr "3 hours" + +msgid "IDS_BR_HEADER_AUTO_REFRESH" +msgstr "Auto refresh" + diff --git a/Po/en_PH.po b/Po/en_PH.po new file mode 100755 index 0000000..d5defb1 --- /dev/null +++ b/Po/en_PH.po @@ -0,0 +1,21 @@ +msgid "IDS_ST_BODY_12_HOURS" +msgstr "12 hours" + +msgid "IDS_ST_BUTTON_CANCEL" +msgstr "Cancel" + +msgid "IDS_BR_OPT_NEVER" +msgstr "Never" + +msgid "IDS_ST_BODY_6_HOURS_TMO" +msgstr "6 hours" + +msgid "IDS_ST_BODY_1_HOUR" +msgstr "1 hour" + +msgid "IDS_ST_BODY_3HOURS" +msgstr "3 hours" + +msgid "IDS_BR_HEADER_AUTO_REFRESH" +msgstr "Auto refresh" + diff --git a/Po/en_US.po b/Po/en_US.po new file mode 100755 index 0000000..d5defb1 --- /dev/null +++ b/Po/en_US.po @@ -0,0 +1,21 @@ +msgid "IDS_ST_BODY_12_HOURS" +msgstr "12 hours" + +msgid "IDS_ST_BUTTON_CANCEL" +msgstr "Cancel" + +msgid "IDS_BR_OPT_NEVER" +msgstr "Never" + +msgid "IDS_ST_BODY_6_HOURS_TMO" +msgstr "6 hours" + +msgid "IDS_ST_BODY_1_HOUR" +msgstr "1 hour" + +msgid "IDS_ST_BODY_3HOURS" +msgstr "3 hours" + +msgid "IDS_BR_HEADER_AUTO_REFRESH" +msgstr "Auto refresh" + diff --git a/Po/es_ES.po b/Po/es_ES.po new file mode 100755 index 0000000..85f5dc5 --- /dev/null +++ b/Po/es_ES.po @@ -0,0 +1,21 @@ +msgid "IDS_ST_BODY_12_HOURS" +msgstr "12 horas" + +msgid "IDS_ST_BUTTON_CANCEL" +msgstr "Cancelar" + +msgid "IDS_BR_OPT_NEVER" +msgstr "Nunca" + +msgid "IDS_ST_BODY_6_HOURS_TMO" +msgstr "6 horas" + +msgid "IDS_ST_BODY_1_HOUR" +msgstr "1 hora" + +msgid "IDS_ST_BODY_3HOURS" +msgstr "3 horas" + +msgid "IDS_BR_HEADER_AUTO_REFRESH" +msgstr "Actualizar automáticamente" + diff --git a/Po/es_MX.po b/Po/es_MX.po new file mode 100755 index 0000000..85f5dc5 --- /dev/null +++ b/Po/es_MX.po @@ -0,0 +1,21 @@ +msgid "IDS_ST_BODY_12_HOURS" +msgstr "12 horas" + +msgid "IDS_ST_BUTTON_CANCEL" +msgstr "Cancelar" + +msgid "IDS_BR_OPT_NEVER" +msgstr "Nunca" + +msgid "IDS_ST_BODY_6_HOURS_TMO" +msgstr "6 horas" + +msgid "IDS_ST_BODY_1_HOUR" +msgstr "1 hora" + +msgid "IDS_ST_BODY_3HOURS" +msgstr "3 horas" + +msgid "IDS_BR_HEADER_AUTO_REFRESH" +msgstr "Actualizar automáticamente" + diff --git a/Po/et.po b/Po/et.po new file mode 100755 index 0000000..c5961f7 --- /dev/null +++ b/Po/et.po @@ -0,0 +1,21 @@ +msgid "IDS_ST_BODY_12_HOURS" +msgstr "12 tundi" + +msgid "IDS_ST_BUTTON_CANCEL" +msgstr "Tühista" + +msgid "IDS_BR_OPT_NEVER" +msgstr "Mitte kunagi" + +msgid "IDS_ST_BODY_6_HOURS_TMO" +msgstr "6 tundi" + +msgid "IDS_ST_BODY_1_HOUR" +msgstr "1 tund" + +msgid "IDS_ST_BODY_3HOURS" +msgstr "3 tundi" + +msgid "IDS_BR_HEADER_AUTO_REFRESH" +msgstr "Automaatne värskendamine" + diff --git a/Po/eu.po b/Po/eu.po new file mode 100755 index 0000000..edbdb81 --- /dev/null +++ b/Po/eu.po @@ -0,0 +1,21 @@ +msgid "IDS_ST_BODY_12_HOURS" +msgstr "12 ordu" + +msgid "IDS_ST_BUTTON_CANCEL" +msgstr "Ezeztatu" + +msgid "IDS_BR_OPT_NEVER" +msgstr "Inoiz ez" + +msgid "IDS_ST_BODY_6_HOURS_TMO" +msgstr "6 ordu" + +msgid "IDS_ST_BODY_1_HOUR" +msgstr "Ordu 1" + +msgid "IDS_ST_BODY_3HOURS" +msgstr "3 ordu" + +msgid "IDS_BR_HEADER_AUTO_REFRESH" +msgstr "Freskatu automatikoki" + diff --git a/Po/fi.po b/Po/fi.po new file mode 100755 index 0000000..2d4b69f --- /dev/null +++ b/Po/fi.po @@ -0,0 +1,21 @@ +msgid "IDS_ST_BODY_12_HOURS" +msgstr "12 tuntia" + +msgid "IDS_ST_BUTTON_CANCEL" +msgstr "Peruuta" + +msgid "IDS_BR_OPT_NEVER" +msgstr "Ei koskaan" + +msgid "IDS_ST_BODY_6_HOURS_TMO" +msgstr "6 tuntia" + +msgid "IDS_ST_BODY_1_HOUR" +msgstr "1 tunti" + +msgid "IDS_ST_BODY_3HOURS" +msgstr "3 tuntia" + +msgid "IDS_BR_HEADER_AUTO_REFRESH" +msgstr "Automaattinen päivitys" + diff --git a/Po/fr_CA.po b/Po/fr_CA.po new file mode 100755 index 0000000..388e4e3 --- /dev/null +++ b/Po/fr_CA.po @@ -0,0 +1,21 @@ +msgid "IDS_ST_BODY_12_HOURS" +msgstr "12 heures" + +msgid "IDS_ST_BUTTON_CANCEL" +msgstr "Annuler" + +msgid "IDS_BR_OPT_NEVER" +msgstr "Jamais" + +msgid "IDS_ST_BODY_6_HOURS_TMO" +msgstr "6 heures" + +msgid "IDS_ST_BODY_1_HOUR" +msgstr "1 heure" + +msgid "IDS_ST_BODY_3HOURS" +msgstr "3 heures" + +msgid "IDS_BR_HEADER_AUTO_REFRESH" +msgstr "Actualisation automatique" + diff --git a/Po/fr_FR.po b/Po/fr_FR.po new file mode 100755 index 0000000..388e4e3 --- /dev/null +++ b/Po/fr_FR.po @@ -0,0 +1,21 @@ +msgid "IDS_ST_BODY_12_HOURS" +msgstr "12 heures" + +msgid "IDS_ST_BUTTON_CANCEL" +msgstr "Annuler" + +msgid "IDS_BR_OPT_NEVER" +msgstr "Jamais" + +msgid "IDS_ST_BODY_6_HOURS_TMO" +msgstr "6 heures" + +msgid "IDS_ST_BODY_1_HOUR" +msgstr "1 heure" + +msgid "IDS_ST_BODY_3HOURS" +msgstr "3 heures" + +msgid "IDS_BR_HEADER_AUTO_REFRESH" +msgstr "Actualisation automatique" + diff --git a/Po/ga.po b/Po/ga.po new file mode 100755 index 0000000..ffadae8 --- /dev/null +++ b/Po/ga.po @@ -0,0 +1,21 @@ +msgid "IDS_ST_BODY_12_HOURS" +msgstr "12 uair an chloig" + +msgid "IDS_ST_BUTTON_CANCEL" +msgstr "Cealaigh" + +msgid "IDS_BR_OPT_NEVER" +msgstr "Choíche" + +msgid "IDS_ST_BODY_6_HOURS_TMO" +msgstr "6 huaire an chloig" + +msgid "IDS_ST_BODY_1_HOUR" +msgstr "1 uair an chloig" + +msgid "IDS_ST_BODY_3HOURS" +msgstr "3 huaire an chloig" + +msgid "IDS_BR_HEADER_AUTO_REFRESH" +msgstr "Uath-athnuaigh" + diff --git a/Po/gl.po b/Po/gl.po new file mode 100755 index 0000000..bdef673 --- /dev/null +++ b/Po/gl.po @@ -0,0 +1,21 @@ +msgid "IDS_ST_BODY_12_HOURS" +msgstr "12 horas" + +msgid "IDS_ST_BUTTON_CANCEL" +msgstr "Cancelar" + +msgid "IDS_BR_OPT_NEVER" +msgstr "Nunca" + +msgid "IDS_ST_BODY_6_HOURS_TMO" +msgstr "6 horas" + +msgid "IDS_ST_BODY_1_HOUR" +msgstr "1 hora" + +msgid "IDS_ST_BODY_3HOURS" +msgstr "3 horas" + +msgid "IDS_BR_HEADER_AUTO_REFRESH" +msgstr "Actualización automática" + diff --git a/Po/hi.po b/Po/hi.po new file mode 100755 index 0000000..673bf72 --- /dev/null +++ b/Po/hi.po @@ -0,0 +1,21 @@ +msgid "IDS_ST_BODY_12_HOURS" +msgstr "12 घंटे" + +msgid "IDS_ST_BUTTON_CANCEL" +msgstr "रद्द" + +msgid "IDS_BR_OPT_NEVER" +msgstr "कभी नहीं" + +msgid "IDS_ST_BODY_6_HOURS_TMO" +msgstr "6 घंटे" + +msgid "IDS_ST_BODY_1_HOUR" +msgstr "1 घंटा" + +msgid "IDS_ST_BODY_3HOURS" +msgstr "3 घंटे" + +msgid "IDS_BR_HEADER_AUTO_REFRESH" +msgstr "स्वतः रीफ्रेश करना" + diff --git a/Po/hr.po b/Po/hr.po new file mode 100755 index 0000000..3705e9a --- /dev/null +++ b/Po/hr.po @@ -0,0 +1,21 @@ +msgid "IDS_ST_BODY_12_HOURS" +msgstr "12 sati" + +msgid "IDS_ST_BUTTON_CANCEL" +msgstr "Prekid" + +msgid "IDS_BR_OPT_NEVER" +msgstr "Nikad" + +msgid "IDS_ST_BODY_6_HOURS_TMO" +msgstr "6 sati" + +msgid "IDS_ST_BODY_1_HOUR" +msgstr "1 sat" + +msgid "IDS_ST_BODY_3HOURS" +msgstr "3 sata" + +msgid "IDS_BR_HEADER_AUTO_REFRESH" +msgstr "Automatsko aktualiziranje" + diff --git a/Po/hu.po b/Po/hu.po new file mode 100755 index 0000000..6eb6d2f --- /dev/null +++ b/Po/hu.po @@ -0,0 +1,21 @@ +msgid "IDS_ST_BODY_12_HOURS" +msgstr "12 óra" + +msgid "IDS_ST_BUTTON_CANCEL" +msgstr "Mégse" + +msgid "IDS_BR_OPT_NEVER" +msgstr "Soha" + +msgid "IDS_ST_BODY_6_HOURS_TMO" +msgstr "6 óra" + +msgid "IDS_ST_BODY_1_HOUR" +msgstr "1 óra" + +msgid "IDS_ST_BODY_3HOURS" +msgstr "3 óra" + +msgid "IDS_BR_HEADER_AUTO_REFRESH" +msgstr "Automatikus frissítés" + diff --git a/Po/hy.po b/Po/hy.po new file mode 100755 index 0000000..ef82cb0 --- /dev/null +++ b/Po/hy.po @@ -0,0 +1,21 @@ +msgid "IDS_ST_BODY_12_HOURS" +msgstr "12 ժամ" + +msgid "IDS_ST_BUTTON_CANCEL" +msgstr "Չեղարկել" + +msgid "IDS_BR_OPT_NEVER" +msgstr "Երբեք" + +msgid "IDS_ST_BODY_6_HOURS_TMO" +msgstr "6 ժամ" + +msgid "IDS_ST_BODY_1_HOUR" +msgstr "1 ժամ" + +msgid "IDS_ST_BODY_3HOURS" +msgstr "3 ժամ" + +msgid "IDS_BR_HEADER_AUTO_REFRESH" +msgstr "Ինքնանորացում" + diff --git a/Po/is.po b/Po/is.po new file mode 100755 index 0000000..6e6c7ac --- /dev/null +++ b/Po/is.po @@ -0,0 +1,21 @@ +msgid "IDS_ST_BODY_12_HOURS" +msgstr "12 klst." + +msgid "IDS_ST_BUTTON_CANCEL" +msgstr "Hætta v." + +msgid "IDS_BR_OPT_NEVER" +msgstr "Aldrei" + +msgid "IDS_ST_BODY_6_HOURS_TMO" +msgstr "6 klst." + +msgid "IDS_ST_BODY_1_HOUR" +msgstr "1 klst." + +msgid "IDS_ST_BODY_3HOURS" +msgstr "3 klst." + +msgid "IDS_BR_HEADER_AUTO_REFRESH" +msgstr "Sjálfvirk uppfærsla" + diff --git a/Po/it_IT.po b/Po/it_IT.po new file mode 100755 index 0000000..62c0eda --- /dev/null +++ b/Po/it_IT.po @@ -0,0 +1,21 @@ +msgid "IDS_ST_BODY_12_HOURS" +msgstr "12 ore" + +msgid "IDS_ST_BUTTON_CANCEL" +msgstr "Annulla" + +msgid "IDS_BR_OPT_NEVER" +msgstr "Mai" + +msgid "IDS_ST_BODY_6_HOURS_TMO" +msgstr "6 ore" + +msgid "IDS_ST_BODY_1_HOUR" +msgstr "1 ora" + +msgid "IDS_ST_BODY_3HOURS" +msgstr "3 ore" + +msgid "IDS_BR_HEADER_AUTO_REFRESH" +msgstr "Aggiornamento automatico" + diff --git a/Po/ja_JP.po b/Po/ja_JP.po new file mode 100755 index 0000000..2c67453 --- /dev/null +++ b/Po/ja_JP.po @@ -0,0 +1,21 @@ +msgid "IDS_ST_BODY_12_HOURS" +msgstr "12時間" + +msgid "IDS_ST_BUTTON_CANCEL" +msgstr "キャンセル" + +msgid "IDS_BR_OPT_NEVER" +msgstr "なし" + +msgid "IDS_ST_BODY_6_HOURS_TMO" +msgstr "6時間" + +msgid "IDS_ST_BODY_1_HOUR" +msgstr "1時間" + +msgid "IDS_ST_BODY_3HOURS" +msgstr "3時間" + +msgid "IDS_BR_HEADER_AUTO_REFRESH" +msgstr "自動更新" + diff --git a/Po/ka.po b/Po/ka.po new file mode 100755 index 0000000..3a99498 --- /dev/null +++ b/Po/ka.po @@ -0,0 +1,21 @@ +msgid "IDS_ST_BODY_12_HOURS" +msgstr "12 საათი" + +msgid "IDS_ST_BUTTON_CANCEL" +msgstr "გაუქმება" + +msgid "IDS_BR_OPT_NEVER" +msgstr "არასოდეს" + +msgid "IDS_ST_BODY_6_HOURS_TMO" +msgstr "6 საათი" + +msgid "IDS_ST_BODY_1_HOUR" +msgstr "1 საათი" + +msgid "IDS_ST_BODY_3HOURS" +msgstr "3 საათი" + +msgid "IDS_BR_HEADER_AUTO_REFRESH" +msgstr "ავტომატური განახლება" + diff --git a/Po/kk.po b/Po/kk.po new file mode 100755 index 0000000..3263792 --- /dev/null +++ b/Po/kk.po @@ -0,0 +1,21 @@ +msgid "IDS_ST_BODY_12_HOURS" +msgstr "12 сағат" + +msgid "IDS_ST_BUTTON_CANCEL" +msgstr "Тоқтату" + +msgid "IDS_BR_OPT_NEVER" +msgstr "Ешқашан" + +msgid "IDS_ST_BODY_6_HOURS_TMO" +msgstr "6 cағат" + +msgid "IDS_ST_BODY_1_HOUR" +msgstr "1 сағат" + +msgid "IDS_ST_BODY_3HOURS" +msgstr "3 сағат" + +msgid "IDS_BR_HEADER_AUTO_REFRESH" +msgstr "Авто жаңарту" + diff --git a/Po/ko_KR.po b/Po/ko_KR.po new file mode 100755 index 0000000..598a4c9 --- /dev/null +++ b/Po/ko_KR.po @@ -0,0 +1,21 @@ +msgid "IDS_ST_BODY_12_HOURS" +msgstr "12시간" + +msgid "IDS_ST_BUTTON_CANCEL" +msgstr "취소" + +msgid "IDS_BR_OPT_NEVER" +msgstr "안 함" + +msgid "IDS_ST_BODY_6_HOURS_TMO" +msgstr "6시간" + +msgid "IDS_ST_BODY_1_HOUR" +msgstr "1시간" + +msgid "IDS_ST_BODY_3HOURS" +msgstr "3시간" + +msgid "IDS_BR_HEADER_AUTO_REFRESH" +msgstr "자동 새로고침" + diff --git a/Po/lt.po b/Po/lt.po new file mode 100755 index 0000000..da32502 --- /dev/null +++ b/Po/lt.po @@ -0,0 +1,21 @@ +msgid "IDS_ST_BODY_12_HOURS" +msgstr "12 valandų" + +msgid "IDS_ST_BUTTON_CANCEL" +msgstr "Atšaukti" + +msgid "IDS_BR_OPT_NEVER" +msgstr "Niekada" + +msgid "IDS_ST_BODY_6_HOURS_TMO" +msgstr "6 valandos" + +msgid "IDS_ST_BODY_1_HOUR" +msgstr "1 valanda" + +msgid "IDS_ST_BODY_3HOURS" +msgstr "3 valandos" + +msgid "IDS_BR_HEADER_AUTO_REFRESH" +msgstr "Automatinis atnaujinimas" + diff --git a/Po/lv.po b/Po/lv.po new file mode 100755 index 0000000..13821cf --- /dev/null +++ b/Po/lv.po @@ -0,0 +1,21 @@ +msgid "IDS_ST_BODY_12_HOURS" +msgstr "12 stundas" + +msgid "IDS_ST_BUTTON_CANCEL" +msgstr "Atcelt" + +msgid "IDS_BR_OPT_NEVER" +msgstr "Nekad" + +msgid "IDS_ST_BODY_6_HOURS_TMO" +msgstr "6 stundas" + +msgid "IDS_ST_BODY_1_HOUR" +msgstr "1 stunda" + +msgid "IDS_ST_BODY_3HOURS" +msgstr "3 stundas" + +msgid "IDS_BR_HEADER_AUTO_REFRESH" +msgstr "Automātiskā atsvaidzināšana" + diff --git a/Po/mk.po b/Po/mk.po new file mode 100755 index 0000000..8b1736e --- /dev/null +++ b/Po/mk.po @@ -0,0 +1,21 @@ +msgid "IDS_ST_BODY_12_HOURS" +msgstr "12 часа" + +msgid "IDS_ST_BUTTON_CANCEL" +msgstr "Откажи" + +msgid "IDS_BR_OPT_NEVER" +msgstr "Никогаш" + +msgid "IDS_ST_BODY_6_HOURS_TMO" +msgstr "6 часа" + +msgid "IDS_ST_BODY_1_HOUR" +msgstr "1 час" + +msgid "IDS_ST_BODY_3HOURS" +msgstr "3 часа" + +msgid "IDS_BR_HEADER_AUTO_REFRESH" +msgstr "Автоматско обновување" + diff --git a/Po/nb.po b/Po/nb.po new file mode 100755 index 0000000..1729025 --- /dev/null +++ b/Po/nb.po @@ -0,0 +1,21 @@ +msgid "IDS_ST_BODY_12_HOURS" +msgstr "12 timer" + +msgid "IDS_ST_BUTTON_CANCEL" +msgstr "Avbryt" + +msgid "IDS_BR_OPT_NEVER" +msgstr "Aldri" + +msgid "IDS_ST_BODY_6_HOURS_TMO" +msgstr "6 timer" + +msgid "IDS_ST_BODY_1_HOUR" +msgstr "1 time" + +msgid "IDS_ST_BODY_3HOURS" +msgstr "3 timer" + +msgid "IDS_BR_HEADER_AUTO_REFRESH" +msgstr "Automatisk oppdatering" + diff --git a/Po/nl_NL.po b/Po/nl_NL.po new file mode 100755 index 0000000..1eef04d --- /dev/null +++ b/Po/nl_NL.po @@ -0,0 +1,21 @@ +msgid "IDS_ST_BODY_12_HOURS" +msgstr "12 uur" + +msgid "IDS_ST_BUTTON_CANCEL" +msgstr "Annuleer" + +msgid "IDS_BR_OPT_NEVER" +msgstr "Nooit" + +msgid "IDS_ST_BODY_6_HOURS_TMO" +msgstr "6 uur" + +msgid "IDS_ST_BODY_1_HOUR" +msgstr "1 uur" + +msgid "IDS_ST_BODY_3HOURS" +msgstr "3 uur" + +msgid "IDS_BR_HEADER_AUTO_REFRESH" +msgstr "Autom. vernieuwen" + diff --git a/Po/pl.po b/Po/pl.po new file mode 100755 index 0000000..ff75551 --- /dev/null +++ b/Po/pl.po @@ -0,0 +1,21 @@ +msgid "IDS_ST_BODY_12_HOURS" +msgstr "12 godz." + +msgid "IDS_ST_BUTTON_CANCEL" +msgstr "Anuluj" + +msgid "IDS_BR_OPT_NEVER" +msgstr "Nigdy" + +msgid "IDS_ST_BODY_6_HOURS_TMO" +msgstr "6 godz." + +msgid "IDS_ST_BODY_1_HOUR" +msgstr "1 godz." + +msgid "IDS_ST_BODY_3HOURS" +msgstr "3 godz." + +msgid "IDS_BR_HEADER_AUTO_REFRESH" +msgstr "Automatyczne odświeżanie" + diff --git a/Po/pt_BR.po b/Po/pt_BR.po new file mode 100755 index 0000000..e4e5127 --- /dev/null +++ b/Po/pt_BR.po @@ -0,0 +1,21 @@ +msgid "IDS_ST_BODY_12_HOURS" +msgstr "12 horas" + +msgid "IDS_ST_BUTTON_CANCEL" +msgstr "Cancelar" + +msgid "IDS_BR_OPT_NEVER" +msgstr "Nunca" + +msgid "IDS_ST_BODY_6_HOURS_TMO" +msgstr "6 horas" + +msgid "IDS_ST_BODY_1_HOUR" +msgstr "1 hora" + +msgid "IDS_ST_BODY_3HOURS" +msgstr "3 horas" + +msgid "IDS_BR_HEADER_AUTO_REFRESH" +msgstr "Atualizar automaticamente" + diff --git a/Po/pt_PT.po b/Po/pt_PT.po new file mode 100755 index 0000000..fb1e22d --- /dev/null +++ b/Po/pt_PT.po @@ -0,0 +1,21 @@ +msgid "IDS_ST_BODY_12_HOURS" +msgstr "12 horas" + +msgid "IDS_ST_BUTTON_CANCEL" +msgstr "Cancelar" + +msgid "IDS_BR_OPT_NEVER" +msgstr "Nunca" + +msgid "IDS_ST_BODY_6_HOURS_TMO" +msgstr "6 horas" + +msgid "IDS_ST_BODY_1_HOUR" +msgstr "1 hora" + +msgid "IDS_ST_BODY_3HOURS" +msgstr "3 horas" + +msgid "IDS_BR_HEADER_AUTO_REFRESH" +msgstr "Actualização auto" + diff --git a/Po/ro.po b/Po/ro.po new file mode 100755 index 0000000..a6c6f82 --- /dev/null +++ b/Po/ro.po @@ -0,0 +1,21 @@ +msgid "IDS_ST_BODY_12_HOURS" +msgstr "12 ore" + +msgid "IDS_ST_BUTTON_CANCEL" +msgstr "Anulare" + +msgid "IDS_BR_OPT_NEVER" +msgstr "Niciodată" + +msgid "IDS_ST_BODY_6_HOURS_TMO" +msgstr "6 ore" + +msgid "IDS_ST_BODY_1_HOUR" +msgstr "1 oră" + +msgid "IDS_ST_BODY_3HOURS" +msgstr "3 ore" + +msgid "IDS_BR_HEADER_AUTO_REFRESH" +msgstr "Reîmprospătare automată" + diff --git a/Po/ru_RU.po b/Po/ru_RU.po new file mode 100755 index 0000000..aa36a8d --- /dev/null +++ b/Po/ru_RU.po @@ -0,0 +1,21 @@ +msgid "IDS_ST_BODY_12_HOURS" +msgstr "12 часов" + +msgid "IDS_ST_BUTTON_CANCEL" +msgstr "Отмена" + +msgid "IDS_BR_OPT_NEVER" +msgstr "Никогда" + +msgid "IDS_ST_BODY_6_HOURS_TMO" +msgstr "6 часов" + +msgid "IDS_ST_BODY_1_HOUR" +msgstr "1 час" + +msgid "IDS_ST_BODY_3HOURS" +msgstr "3 часа" + +msgid "IDS_BR_HEADER_AUTO_REFRESH" +msgstr "Автообновление" + diff --git a/Po/sk.po b/Po/sk.po new file mode 100755 index 0000000..dab9cf4 --- /dev/null +++ b/Po/sk.po @@ -0,0 +1,21 @@ +msgid "IDS_ST_BODY_12_HOURS" +msgstr "12 hodín" + +msgid "IDS_ST_BUTTON_CANCEL" +msgstr "Zrušiť" + +msgid "IDS_BR_OPT_NEVER" +msgstr "Nikdy" + +msgid "IDS_ST_BODY_6_HOURS_TMO" +msgstr "6 hodín" + +msgid "IDS_ST_BODY_1_HOUR" +msgstr "1 hodina" + +msgid "IDS_ST_BODY_3HOURS" +msgstr "3 hodiny" + +msgid "IDS_BR_HEADER_AUTO_REFRESH" +msgstr "Automatické obnovenie" + diff --git a/Po/sl.po b/Po/sl.po new file mode 100755 index 0000000..2f565d2 --- /dev/null +++ b/Po/sl.po @@ -0,0 +1,21 @@ +msgid "IDS_ST_BODY_12_HOURS" +msgstr "12 ur" + +msgid "IDS_ST_BUTTON_CANCEL" +msgstr "Prekliči" + +msgid "IDS_BR_OPT_NEVER" +msgstr "Nikoli" + +msgid "IDS_ST_BODY_6_HOURS_TMO" +msgstr "6 ur" + +msgid "IDS_ST_BODY_1_HOUR" +msgstr "1 ura" + +msgid "IDS_ST_BODY_3HOURS" +msgstr "3 ure" + +msgid "IDS_BR_HEADER_AUTO_REFRESH" +msgstr "Samodejno osveževanje" + diff --git a/Po/sr.po b/Po/sr.po new file mode 100755 index 0000000..df0a5d8 --- /dev/null +++ b/Po/sr.po @@ -0,0 +1,21 @@ +msgid "IDS_ST_BODY_12_HOURS" +msgstr "12 sati" + +msgid "IDS_ST_BUTTON_CANCEL" +msgstr "Poništi" + +msgid "IDS_BR_OPT_NEVER" +msgstr "Nikad" + +msgid "IDS_ST_BODY_6_HOURS_TMO" +msgstr "6 sati" + +msgid "IDS_ST_BODY_1_HOUR" +msgstr "1 sat" + +msgid "IDS_ST_BODY_3HOURS" +msgstr "3 sata" + +msgid "IDS_BR_HEADER_AUTO_REFRESH" +msgstr "Automatsko osvežavanje" + diff --git a/Po/sv.po b/Po/sv.po new file mode 100755 index 0000000..7016603 --- /dev/null +++ b/Po/sv.po @@ -0,0 +1,21 @@ +msgid "IDS_ST_BODY_12_HOURS" +msgstr "12 timmar" + +msgid "IDS_ST_BUTTON_CANCEL" +msgstr "Avbryt" + +msgid "IDS_BR_OPT_NEVER" +msgstr "Aldrig" + +msgid "IDS_ST_BODY_6_HOURS_TMO" +msgstr "6 timmar" + +msgid "IDS_ST_BODY_1_HOUR" +msgstr "1 timme" + +msgid "IDS_ST_BODY_3HOURS" +msgstr "3 timmar" + +msgid "IDS_BR_HEADER_AUTO_REFRESH" +msgstr "Uppdatera automatiskt" + diff --git a/Po/tr_TR.po b/Po/tr_TR.po new file mode 100755 index 0000000..6cc7c51 --- /dev/null +++ b/Po/tr_TR.po @@ -0,0 +1,21 @@ +msgid "IDS_ST_BODY_12_HOURS" +msgstr "12 saat" + +msgid "IDS_ST_BUTTON_CANCEL" +msgstr "İptal" + +msgid "IDS_BR_OPT_NEVER" +msgstr "Hiçbir zaman" + +msgid "IDS_ST_BODY_6_HOURS_TMO" +msgstr "6 saat" + +msgid "IDS_ST_BODY_1_HOUR" +msgstr "1 saat" + +msgid "IDS_ST_BODY_3HOURS" +msgstr "3 saat" + +msgid "IDS_BR_HEADER_AUTO_REFRESH" +msgstr "Otomatik yenileme" + diff --git a/Po/uk.po b/Po/uk.po new file mode 100755 index 0000000..b048476 --- /dev/null +++ b/Po/uk.po @@ -0,0 +1,21 @@ +msgid "IDS_ST_BODY_12_HOURS" +msgstr "12 годин" + +msgid "IDS_ST_BUTTON_CANCEL" +msgstr "Скасувати" + +msgid "IDS_BR_OPT_NEVER" +msgstr "Ніколи" + +msgid "IDS_ST_BODY_6_HOURS_TMO" +msgstr "6 годин" + +msgid "IDS_ST_BODY_1_HOUR" +msgstr "1 годину" + +msgid "IDS_ST_BODY_3HOURS" +msgstr "3 години" + +msgid "IDS_BR_HEADER_AUTO_REFRESH" +msgstr "Автоматичне оновлення" + diff --git a/Po/uz.po b/Po/uz.po new file mode 100755 index 0000000..d12f048 --- /dev/null +++ b/Po/uz.po @@ -0,0 +1,21 @@ +msgid "IDS_ST_BODY_12_HOURS" +msgstr "12 soat" + +msgid "IDS_ST_BUTTON_CANCEL" +msgstr "Bekor q." + +msgid "IDS_BR_OPT_NEVER" +msgstr "Hech qachon" + +msgid "IDS_ST_BODY_6_HOURS_TMO" +msgstr "6 saot" + +msgid "IDS_ST_BODY_1_HOUR" +msgstr "1 soat" + +msgid "IDS_ST_BODY_3HOURS" +msgstr "3 soat" + +msgid "IDS_BR_HEADER_AUTO_REFRESH" +msgstr "Avtomatik yangilash" + diff --git a/Po/zh_CN.po b/Po/zh_CN.po new file mode 100755 index 0000000..975d35f --- /dev/null +++ b/Po/zh_CN.po @@ -0,0 +1,21 @@ +msgid "IDS_ST_BODY_12_HOURS" +msgstr "12 小时" + +msgid "IDS_ST_BUTTON_CANCEL" +msgstr "取消" + +msgid "IDS_BR_OPT_NEVER" +msgstr "从不" + +msgid "IDS_ST_BODY_6_HOURS_TMO" +msgstr "6 小时" + +msgid "IDS_ST_BODY_1_HOUR" +msgstr "1 小时" + +msgid "IDS_ST_BODY_3HOURS" +msgstr "3 小时" + +msgid "IDS_BR_HEADER_AUTO_REFRESH" +msgstr "自动刷新" + diff --git a/Po/zh_HK.po b/Po/zh_HK.po new file mode 100755 index 0000000..4a55610 --- /dev/null +++ b/Po/zh_HK.po @@ -0,0 +1,21 @@ +msgid "IDS_ST_BODY_12_HOURS" +msgstr "12 小時" + +msgid "IDS_ST_BUTTON_CANCEL" +msgstr "取消" + +msgid "IDS_BR_OPT_NEVER" +msgstr "永不" + +msgid "IDS_ST_BODY_6_HOURS_TMO" +msgstr "6 小時" + +msgid "IDS_ST_BODY_1_HOUR" +msgstr "1 小時" + +msgid "IDS_ST_BODY_3HOURS" +msgstr "3 小時" + +msgid "IDS_BR_HEADER_AUTO_REFRESH" +msgstr "自動重新整理" + diff --git a/Po/zh_SG.po b/Po/zh_SG.po new file mode 100755 index 0000000..6a5ab94 --- /dev/null +++ b/Po/zh_SG.po @@ -0,0 +1,21 @@ +msgid "IDS_ST_BODY_12_HOURS" +msgstr "12小时" + +msgid "IDS_ST_BUTTON_CANCEL" +msgstr "取消" + +msgid "IDS_BR_OPT_NEVER" +msgstr "从不" + +msgid "IDS_ST_BODY_6_HOURS_TMO" +msgstr "6小时" + +msgid "IDS_ST_BODY_1_HOUR" +msgstr "1小时" + +msgid "IDS_ST_BODY_3HOURS" +msgstr "3 小时" + +msgid "IDS_BR_HEADER_AUTO_REFRESH" +msgstr "自动刷新" + diff --git a/Po/zh_TW.po b/Po/zh_TW.po new file mode 100755 index 0000000..4a55610 --- /dev/null +++ b/Po/zh_TW.po @@ -0,0 +1,21 @@ +msgid "IDS_ST_BODY_12_HOURS" +msgstr "12 小時" + +msgid "IDS_ST_BUTTON_CANCEL" +msgstr "取消" + +msgid "IDS_BR_OPT_NEVER" +msgstr "永不" + +msgid "IDS_ST_BODY_6_HOURS_TMO" +msgstr "6 小時" + +msgid "IDS_ST_BODY_1_HOUR" +msgstr "1 小時" + +msgid "IDS_ST_BODY_3HOURS" +msgstr "3 小時" + +msgid "IDS_BR_HEADER_AUTO_REFRESH" +msgstr "自動重新整理" + diff --git a/cmake/OptionsTizen.cmake b/cmake/OptionsTizen.cmake new file mode 100644 index 0000000..050d877 --- /dev/null +++ b/cmake/OptionsTizen.cmake @@ -0,0 +1,3 @@ +#OptionsTizen.cmake + +#ADD_DEFINITIONS(-DENABLE_WEB_PROVIDER_LOAD=1) diff --git a/data/200.livebox.web-provider.patch.sh b/data/200.livebox.web-provider.patch.sh new file mode 100644 index 0000000..039f88e --- /dev/null +++ b/data/200.livebox.web-provider.patch.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +setfattr -n security.capability -v 0sAQAAAgABAAAAAAAAAgAAAAAAAAA= /usr/apps/livebox.web-provider/bin/web-provider diff --git a/data/web_provider_db.sql b/data/web_provider_db.sql new file mode 100644 index 0000000..df1a0c5 --- /dev/null +++ b/data/web_provider_db.sql @@ -0,0 +1,11 @@ +BEGIN TRANSACTION; +CREATE TABLE LiveboxInfo ( + box_id TEXT not null, + app_id TEXT not null, + box_type TEXT not null, + auto_launch INT, + mouse_event INT, + pd_fast_open INT, + PRIMARY KEY (box_id) , +CHECK(1) ); +COMMIT; diff --git a/data/web_provider_reset_db.sh b/data/web_provider_reset_db.sh new file mode 100644 index 0000000..d1bd966 --- /dev/null +++ b/data/web_provider_reset_db.sh @@ -0,0 +1,36 @@ +#!/bin/sh +# Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved +# +# Licensed under the Flora License, Version 1.1 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://floralicense.org/license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +web_provider_db="/opt/usr/dbspace/.web_provider.db" +web_provider_sql="/usr/share/web-provider/web_provider_db.sql" + +if [ -f $web_provider_db ]; then + /bin/echo "DB already exists." +else + /bin/echo "create web livebox DB..." + /bin/rm -f $web_provider_db + /bin/rm -f $web_provider_db-journal + sql="PRAGMA journal_mode = PERSIST;" + /usr/bin/sqlite3 $web_provider_db "$sql" + sql=".read "$web_provider_sql + /usr/bin/sqlite3 $web_provider_db "$sql" + /bin/touch $web_provider_db-journal + /bin/chown 0:6026 $web_provider_db + /bin/chown 0:6026 $web_provider_db-journal + /bin/chmod 660 $web_provider_db + /bin/chmod 660 $web_provider_db-journal + /bin/echo "finish creation of db." +fi diff --git a/livebox.web-provider.manifest b/livebox.web-provider.manifest new file mode 100755 index 0000000..a3b72f9 --- /dev/null +++ b/livebox.web-provider.manifest @@ -0,0 +1,16 @@ +<manifest> + <!-- web provider label --> + <define> + <domain name="livebox.web-provider"/> + <provide> + <label name="livebox.web-provider::db" /> + </provide> + </define> + <assign> + <filesystem path="/usr/lib/libweb-provider*.so*" label="_" /> + <filesystem path="/usr/lib/web-provider/libweb-provider*.so*" label="_" /> + </assign> + <request> + <domain name="livebox.web-provider" /> + </request> +</manifest> diff --git a/livebox.web-provider.mobile.rule b/livebox.web-provider.mobile.rule new file mode 100755 index 0000000..d64ce16 --- /dev/null +++ b/livebox.web-provider.mobile.rule @@ -0,0 +1,89 @@ +livebox.web-provider livebox.web-provider::db rwxat +livebox.web-provider system::vconf rwxat +livebox.web-provider system::homedir rwxat +livebox.web-provider system::share rwxat +livebox.web-provider device::app_logging rwxat +livebox.web-provider data-provider-master rwxat +livebox.web-provider data-provider-master::share rwxat +livebox.web-provider data-provider-master::data rwxat +livebox.web-provider data-provider-master::db rwxat +livebox.web-provider wrt-security-daemon::db rwxat +livebox.web-provider wrt-security-daemon rwxat +livebox.web-provider cert-svc rwxat +livebox.web-provider wrt-commons::db_wrt rwxat +livebox.web-provider syslogd rwxat +livebox.web-provider xorg rwxat +livebox.web-provider isf rwxat +livebox.web-provider dbus rwxat +livebox.web-provider e17 rwxat +livebox.web-provider pulseaudio rwxat +livebox.web-provider ail::db rwxat +livebox.web-provider sys-assert::core rwxat +livebox.web-provider resman::db rwxat +livebox.web-provider webkit2-efl rwxat +livebox.web-provider app-svc rwxat +livebox.web-provider app-svc::db rwxat +livebox.web-provider svi-data rwxat +livebox.web-provider sound_server rwxat +livebox.web-provider privacy-manager::db rwxat +livebox.web-provider immvibed rwxat +livebox.web-provider alarm-server::alarm rwxat +livebox.web-provider allshare::svc rwxat +livebox.web-provider aul::launch rwxat +livebox.web-provider aul::terminate rwxat +livebox.web-provider badge::db rwxat +livebox.web-provider browser-provider::bookmark rwxat +livebox.web-provider bt-service::admin rwxat +livebox.web-provider bt-service::gap rwxat +livebox.web-provider bt-service::manager rwxat +livebox.web-provider bt-service::spp rwxat +livebox.web-provider calendar-service rwxat +livebox.web-provider calendar-service::svc rwxat +livebox.web-provider contacts-service rwxat +livebox.web-provider contacts-service::phonelog rwxat +livebox.web-provider contacts-service::svc rwxat +livebox.web-provider data-provider-master::notification rwxat +livebox.web-provider data-provider-master::notification.client rwxat +livebox.web-provider data-provider-master::badge rwxat +livebox.web-provider data-provider-master::badge.client rwxat +livebox.web-provider device::bklight rwxat +livebox.web-provider deviced rwxat +livebox.web-provider email-service::db rwxat +livebox.web-provider mdm-server rwxat +livebox.web-provider media-data::db rwxat +livebox.web-provider media-server rwxat +livebox.web-provider msg-service rwxat +livebox.web-provider msg-service::db rwxat +livebox.web-provider msg-service::read rwxat +livebox.web-provider msg-service::smstrigger rwxat +livebox.web-provider msg-service::write rwxat +livebox.web-provider msg-service::db rwxat +livebox.web-provider nfc-manager rwxat +livebox.web-provider nfc-manager::admin rwxat +livebox.web-provider nfc-manager::common rwxat +livebox.web-provider nfc-manager::p2p rwxat +livebox.web-provider nfc-manager::tag rwxat +livebox.web-provider notification::db rwxat +livebox.web-provider oma-ds-agent rwxat +livebox.web-provider oma-ds-agent::cfg rwxat +livebox.web-provider oma-ds-agent::svc rwxat +livebox.web-provider org.tizen.setting::default-resources rwxat +livebox.web-provider osp::datacontrol rwxat +livebox.web-provider pkgmgr::db rwxat +livebox.web-provider pkgmgr::info rwxat +livebox.web-provider pkgmgr::svc rwxat +livebox.web-provider push-service rwxat +livebox.web-provider smartcard-service rwxat +livebox.web-provider system::media rwxat +livebox.web-provider system::use_internet rwxat +livebox.web-provider sync_agent_frwk::oma-ds rwxat +livebox.web-provider telephony_framework::api_modem rwxat +livebox.web-provider telephony_framework::api_sim rwxat +livebox.web-provider security-server::api-data-share rwxat +system::use_internet livebox.web-provider rwxat +calendar-service livebox.web-provider rwxat +contacts-service livebox.web-provider rwxat +media-server livebox.web-provider rwxat +nfc-manager livebox.web-provider rwxat +sync_agent_frwk::oma-ds livebox.web-provider rwxat +system::use_internet livebox.web-provider rwxat diff --git a/livebox.web-provider.rule b/livebox.web-provider.rule new file mode 100755 index 0000000..9410483 --- /dev/null +++ b/livebox.web-provider.rule @@ -0,0 +1,40 @@ +livebox.web-provider livebox.web-provider::db rwxat +livebox.web-provider system::vconf rwxat +livebox.web-provider system::vconf_inhouse rwxat +livebox.web-provider system::vconf_multimedia rwxat +livebox.web-provider system::vconf_network rwxat +livebox.web-provider system::vconf_system rwxat +livebox.web-provider system::homedir rwxat +livebox.web-provider system::use_internet rwxat +livebox.web-provider system::media rwxat +livebox.web-provider system::share rwxat +livebox.web-provider device::app_logging rwxat +livebox.web-provider data-provider-master rwxat +livebox.web-provider data-provider-master::share rwxat +livebox.web-provider data-provider-master::data rwxat +livebox.web-provider data-provider-master::db rwxat +livebox.web-provider wrt-security-daemon::db rwxat +livebox.web-provider wrt-security-daemon rwxat +livebox.web-provider cert-svc rwxat +livebox.web-provider wrt-commons::db_wrt rwxat +livebox.web-provider syslogd rwxat +livebox.web-provider xorg rwxat +livebox.web-provider isf rwxat +livebox.web-provider dbus rwxat +livebox.web-provider e17 rwxat +livebox.web-provider pulseaudio rwxat +livebox.web-provider ail::db rwxat +livebox.web-provider sys-assert::core rwxat +livebox.web-provider webkit2-efl rwxat +livebox.web-provider app-svc rwxat +livebox.web-provider app-svc::db rwxat +livebox.web-provider svi-data rwxat +livebox.web-provider sound_server rwxat +livebox.web-provider pkgmgr::db rwxat +livebox.web-provider privacy-manager::db rwxat +livebox.web-provider media-data::db rwxat +livebox.web-provider immvibed rwxat +system::use_internet livebox.web-provider rwxat +livebox.web-provider aul::launch rwxat +livebox.web-provider aul::terminate rwxat +livebox.web-provider tts-server rwxat diff --git a/livebox.web-provider.xml b/livebox.web-provider.xml new file mode 100644 index 0000000..1632996 --- /dev/null +++ b/livebox.web-provider.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8" ?> +<manifest xmlns="http://tizen.org/ns/packages" package="livebox.web-provider" version="1.0" install-location="internal-only"> + <label>Web Dynamic Box Provider</label> + <author email="yunchan.cho@samsung.com" href="www.samsung.com">Yunchan Cho</author> + <description>Web Dynamic Box Provider Executable</description> + <ui-application appid="dbox.web-provider" exec="/usr/apps/livebox.web-provider/bin/web-provider" nodisplay="true" multiple="false" type="capp" taskmanage="false"> + <icon>livebox.web-provider.png</icon> + <label>Web Dynamic Box Provider</label> + <label xml:lang="en-us">Web Dynamic Box Provider</label> + <application-service> + <operation name="http://tizen.org/appcontrol/operation/dynamicbox/web/update"/> + <uri name="box-service"/> + </application-service> + <application-service> + <operation name="http://tizen.org/appcontrol/operation/dynamicbox/web/remove"/> + </application-service> + </ui-application> +</manifest> diff --git a/packaging/livebox.web-provider.spec b/packaging/livebox.web-provider.spec new file mode 100644 index 0000000..18a98c5 --- /dev/null +++ b/packaging/livebox.web-provider.spec @@ -0,0 +1,121 @@ +#git:framework/web/web-provider +Name: livebox.web-provider +Summary: web framework for livebox +Version: 1.100_w2 +Release: 1 +Group: main/app +License: Flora License, Version 1.1 +Source0: %{name}-%{version}.tar.gz +BuildRequires: attr +BuildRequires: cmake, gettext-tools +BuildRequires: libcap, libcap-devel +BuildRequires: pkgconfig(ail) +BuildRequires: pkgconfig(aul) +BuildRequires: pkgconfig(appcore-efl) +BuildRequires: pkgconfig(dlog) +BuildRequires: pkgconfig(bundle) +BuildRequires: pkgconfig(eina) +BuildRequires: pkgconfig(ecore) +BuildRequires: pkgconfig(ecore-x) +BuildRequires: pkgconfig(evas) +BuildRequires: pkgconfig(ecore-evas) +BuildRequires: pkgconfig(elementary) +BuildRequires: pkgconfig(efl-assist) +BuildRequires: pkgconfig(ewebkit2) +BuildRequires: pkgconfig(wrt-core) +BuildRequires: pkgconfig(xmlsec1) +BuildRequires: pkgconfig(dpl-efl) +BuildRequires: pkgconfig(provider) +BuildRequires: pkgconfig(livebox-service) +BuildRequires: pkgconfig(glib-2.0) +BuildRequires: pkgconfig(json-glib-1.0) +BuildRequires: pkgconfig(capi-appfw-application) +BuildRequires: pkgconfig(libsmack) + +Requires(post): attr + +%description +This is web framework responsible to manage liveboxes that consist of web contents + +%package devel +Summary: Files for web provider devel. +Group: Development/Libraries +Requires: %{name} = %{version}-%{release} + +%description devel +Web Provider library (dev) + +%prep +%setup -q + +%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" + ln -sf src_wearable src +%else + %define device_profile "mobile" + ln -sf src_mobile src + rm livebox.web-provider.rule + mv livebox.web-provider.mobile.rule livebox.web-provider.rule +%endif + +cmake . \ + -DCMAKE_INSTALL_PREFIX=%{_prefix} \ + -DCMAKE_PROJECT_VERSION=%{version} \ + -DDEVICE_PROFILE=%{?device_profile:%device_profile} + +#-fpie LDFLAGS="${LDFLAGS} -pie -O3" +CXXFLAGS="${CXXFLAGS} -Wall -Winline -Werror -fno-builtin-malloc" make %{?jobs:-j%jobs} + +%install +rm -rf %{buildroot} +mkdir -p %{buildroot}/usr/share/license +cp LICENSE.Flora %{buildroot}/usr/share/license/%{name} +%make_install +%define app_data /opt/usr/apps/livebox.web-provider/data +mkdir -p %{buildroot}%{app_data} + +%post +killall -9 web-provider +/usr/bin/web_provider_reset_db.sh +echo "smack setting..." +chsmack -a 'livebox.web-provider::db' /opt/usr/dbspace/.web_provider.db +chsmack -a 'livebox.web-provider::db' /opt/usr/dbspace/.web_provider.db-journal +setfattr -n security.capability -v 0sAQAAAgABAAAAAAAAAgAAAAAAAAA= %{_prefix}/apps/livebox.web-provider/bin/web-provider +chown 5000:5000 %{app_data} +chmod 755 %{app_data} + +%files -n livebox.web-provider +%manifest livebox.web-provider.manifest +%defattr(-,root,root,-) +%{_libdir}/*.so* +%{_libdir}/web-provider/*.so* +%{_libdir}/web-provider/*.json +%{_datadir}/web-provider/* +%attr(755,root,root) %{_bindir}/web_provider_reset_db.sh +%{_prefix}/apps/livebox.web-provider/bin/web-provider +%{_datarootdir}/packages/livebox.web-provider.xml +%{_prefix}/share/res/* + +%if "%{_repository}" == "wearable" +# wearable + %{_sysconfdir}/smack/accesses2.d/livebox.web-provider.rule +%else +# mobile + %{_sysconfdir}/smack/accesses.d/livebox.web-provider.rule +%endif + +%{app_data} +%{_datadir}/license/%{name} +%attr(700,root,root) /etc/opt/upgrade/*.patch.sh + +%files devel +%defattr(-,root,root,-) +%{_includedir}/web-provider/* +%{_libdir}/pkgconfig/*.pc diff --git a/pkgconfig/web-provider-svc.pc.in b/pkgconfig/web-provider-svc.pc.in new file mode 100644 index 0000000..e85274f --- /dev/null +++ b/pkgconfig/web-provider-svc.pc.in @@ -0,0 +1,11 @@ +prefix=/usr +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: web-provider +Description: web-provider library +Version: @PROJECT_VERSION@ +Requires: db-util glib-2.0 json-glib-1.0 ecore ecore-evas evas eina provider ewebkit2 dlog +Libs: -lweb-provider-api -lweb-provider-core -L${libdir} +Cflags: -I${includedir}/web-provider -I${includedir}/web-provider/API -I${includedir}/web-provider/Core -I${includedir}/web-provider/Plugin diff --git a/pkgconfig/web-provider.pc.in b/pkgconfig/web-provider.pc.in new file mode 100644 index 0000000..e85274f --- /dev/null +++ b/pkgconfig/web-provider.pc.in @@ -0,0 +1,11 @@ +prefix=/usr +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: web-provider +Description: web-provider library +Version: @PROJECT_VERSION@ +Requires: db-util glib-2.0 json-glib-1.0 ecore ecore-evas evas eina provider ewebkit2 dlog +Libs: -lweb-provider-api -lweb-provider-core -L${libdir} +Cflags: -I${includedir}/web-provider -I${includedir}/web-provider/API -I${includedir}/web-provider/Core -I${includedir}/web-provider/Plugin diff --git a/src_mobile/API/CMakeLists.txt b/src_mobile/API/CMakeLists.txt new file mode 100644 index 0000000..bc033fd --- /dev/null +++ b/src_mobile/API/CMakeLists.txt @@ -0,0 +1,68 @@ +# Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved +# +# Licensed under the Flora License, Version 1.1 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://floralicense.org/license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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) + +SET(TARGET_NAME ${TARGET_API}) +SET(DEPS ${TARGET_NAME}_DEPS) + +PKG_CHECK_MODULES(${DEPS} + db-util + glib-2.0 + json-glib-1.0 + dlog + REQUIRED +) +ADD_DEFINITIONS(${${DEPS}_CFLAGS}) + +SET(SRCS + ${CMAKE_CURRENT_SOURCE_DIR}/SqliteDB.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/web_provider_livebox_info.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/web_provider_plugin_info.cpp +) + +SET(HEADERS + ${${DEPS}_INCLUDE_DIRS} + ${CMAKE_CURRENT_SOURCE_DIR} +) +INCLUDE_DIRECTORIES(${HEADERS}) + +ADD_LIBRARY(${TARGET_NAME} SHARED ${SRCS}) + +SET_TARGET_PROPERTIES(${TARGET_NAME} PROPERTIES + COMPILE_FLAGS -fPIC + LINK_FLAGS "-Wl,--as-needed -Wl,--hash-style=both" +) + +SET_TARGET_PROPERTIES(${TARGET_NAME} + PROPERTIES + SOVERSION ${CMAKE_PROJECT_API_VERSION} + VERSION ${CMAKE_PROJECT_VERSION} +) + +TARGET_LINK_LIBRARIES(${TARGET_NAME} + ${${DEPS}_LDFLAGS} "-ldl" + ${${DEPS}_LIBRARIES} +) + +INSTALL(TARGETS ${TARGET_NAME} + DESTINATION lib + PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE + GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE +) + +GET_FILENAME_COMPONENT(CURRENT_DIR_NAME ${CMAKE_CURRENT_SOURCE_DIR} NAME) +INSTALL_FILE(web-provider-info.h include/${PROJECT_NAME}/${CURRENT_DIR_NAME}) # Deprecated +INSTALL_FILE(web_provider_livebox_info.h include/${PROJECT_NAME}/${CURRENT_DIR_NAME}) +INSTALL_FILE(web_provider_plugin_info.h include/${PROJECT_NAME}/${CURRENT_DIR_NAME}) diff --git a/src_mobile/API/SqliteDB.cpp b/src_mobile/API/SqliteDB.cpp new file mode 100644 index 0000000..fcd9132 --- /dev/null +++ b/src_mobile/API/SqliteDB.cpp @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file SqliteDB.cpp + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#include <string> +#include <cstring> +#include <cstdarg> +#include <sqlite3.h> +#include <db-util.h> + +#include "SqliteDB.h" + +SqliteDB::SqliteDB(std::string dbPath) + : m_path(dbPath) + , m_handle(NULL) + , m_stmt(NULL) +{ +} + +SqliteDB::~SqliteDB() +{ +} + +bool SqliteDB::openDB() +{ + closeDB(); + int ret; + ret = db_util_open(m_path.c_str(), &m_handle, DB_UTIL_REGISTER_HOOK_METHOD); + if (ret != SQLITE_OK) { + return false; + } + + return true; +} + +void SqliteDB::closeDB() +{ + if (!m_handle) { + return; + } + + if (!m_stmt) { + db_util_close(m_handle); + m_handle = NULL; + return; + } + + sqlite3_finalize(m_stmt); + db_util_close(m_handle); + m_stmt = NULL; + m_handle = NULL; +} + +bool SqliteDB::setCommand(std::string& query, const char* fmt, ...) +{ + if (!m_handle || !fmt) { + return false; + } + + int ret = + sqlite3_prepare_v2(m_handle, query.c_str(), -1, &m_stmt, NULL); + + if (ret != SQLITE_OK) { + return false; + } + + // bind values to query + int intValue; + char* stringValue; + + va_list ap; + va_start(ap, fmt); + for (unsigned int i = 0; i < strlen(fmt); i++) { + switch (fmt[i]) { + case 'i': + intValue = va_arg(ap, int); + ret = sqlite3_bind_int(m_stmt, i + 1, intValue); + if (ret != SQLITE_OK) { + va_end(ap); + return false; + } + break; + case 's': + stringValue = va_arg(ap, char*); + ret = sqlite3_bind_text(m_stmt, i + 1, stringValue, -1, NULL); + if (ret != SQLITE_OK) { + va_end(ap); + return false; + } + break; + default: + break; + } + } + va_end(ap); + + return true; +} + +bool SqliteDB::executeCommand() +{ + int ret = + sqlite3_step(m_stmt); + + if (ret != SQLITE_ROW) { + return false; + } + + return true; +} + +const char* SqliteDB::getText(int col) +{ + const char* ret = + reinterpret_cast<const char*>(sqlite3_column_text(m_stmt, col)); + + return ret; +} + +int SqliteDB::getInt(int col) +{ + return sqlite3_column_int(m_stmt, col); +} diff --git a/src_mobile/API/SqliteDB.h b/src_mobile/API/SqliteDB.h new file mode 100644 index 0000000..0f7c993 --- /dev/null +++ b/src_mobile/API/SqliteDB.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file SqliteDB.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef SQLITE_DB_H +#define SQLITE_DB_H + +#include <string> +#include <sqlite3.h> + +class SqliteDB { + public: + bool openDB(); + void closeDB(); + bool setCommand(std::string& query, const char* fmt, ...); + bool executeCommand(); + const char* getText(int col); + int getInt(int col); + + explicit SqliteDB(const std::string dbPath); + ~SqliteDB(); + + private: + std::string m_path; + sqlite3* m_handle; + sqlite3_stmt* m_stmt; +}; + +#endif // SQLITE_DB_H diff --git a/src_mobile/API/WebProviderDB.h b/src_mobile/API/WebProviderDB.h new file mode 100644 index 0000000..e6f14f6 --- /dev/null +++ b/src_mobile/API/WebProviderDB.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file WebProviderDB.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef LIVEBOX_DB_H +#define LIVEBOX_DB_H + +#include <string> +#include "SqliteDB.h" + +const std::string dbPath("/opt/usr/dbspace/.web_provider.db"); + +class WebProviderDB : public SqliteDB { + public: + WebProviderDB() : SqliteDB (dbPath) {}; + ~WebProviderDB() {}; +}; + +#endif //LIVEBOX_DB_H diff --git a/src_mobile/API/web-provider-info.h b/src_mobile/API/web-provider-info.h new file mode 100644 index 0000000..6d9a8b8 --- /dev/null +++ b/src_mobile/API/web-provider-info.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file web-provider-info.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef WEB_PROVIDER_INFO_H +#define WEB_PROVIDER_INFO_H + +#include <API/web_provider_livebox_info.h> + +#endif //WEB_PROVIDER_INFO_H diff --git a/src_mobile/API/web_provider_livebox_info.cpp b/src_mobile/API/web_provider_livebox_info.cpp new file mode 100644 index 0000000..731a935 --- /dev/null +++ b/src_mobile/API/web_provider_livebox_info.cpp @@ -0,0 +1,316 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file web_provider_livebox_info.cpp + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#include <cstring> +#include <memory> +#include "WebProviderDB.h" +#include "web_provider_livebox_info.h" + +static const std::string infoTable("LiveboxInfo"); + +enum InfoTableField { + BOX_ID = 0, + APP_ID, + BOX_TYPE, + AUTO_LAUNCH, + MOUSE_EVENT, + PD_FAST_OPEN, +}; + +// TODO this default type should be retrieved more automatically +static const std::string defaultBoxType("app"); + +const char* web_provider_livebox_get_default_type() +{ + return defaultBoxType.c_str(); +} + +const char* web_provider_livebox_get_box_type(const char* box_id) +{ + if (!box_id) { + return NULL; + } + + std::shared_ptr<WebProviderDB> handle(new WebProviderDB()); + if (!handle->openDB()) { + return NULL; + } + + std::string query = "select * from " + infoTable + " where box_id = ?"; + if (!handle->setCommand(query, "s", box_id)) { + handle->closeDB(); + return NULL; + } + + if (!handle->executeCommand()) { + handle->closeDB(); + return NULL; + } + + const char* box_type = handle->getText(InfoTableField::BOX_TYPE); + const char* box_type_dup = NULL; + + if (box_type) { + box_type_dup = strdup(box_type); + } + + handle->closeDB(); + + return box_type_dup; +} + +const char* web_provider_livebox_get_app_id(const char* box_id) +{ + if (!box_id) { + return NULL; + } + + std::shared_ptr<WebProviderDB> handle(new WebProviderDB()); + if (!handle->openDB()) { + return NULL; + } + + std::string query = "select * from " + infoTable + " where box_id = ?"; + if (!handle->setCommand(query, "s", box_id)) { + handle->closeDB(); + return NULL; + } + + if (!handle->executeCommand()) { + handle->closeDB(); + return NULL; + } + + const char* app_id = handle->getText(InfoTableField::APP_ID); + const char* app_id_dup = NULL; + + if (app_id) { + app_id_dup = strdup(app_id); + } + + handle->closeDB(); + + return app_id_dup; +} + +int web_provider_livebox_get_auto_launch(const char* box_id) +{ + if (!box_id) { + return 0; + } + + std::shared_ptr<WebProviderDB> handle(new WebProviderDB()); + if (!handle->openDB()) { + return 0; + } + + std::string query = "select * from " + infoTable + " where box_id = ?"; + if (!handle->setCommand(query, "s", box_id)) { + handle->closeDB(); + return 0; + } + + if (!handle->executeCommand()) { + handle->closeDB(); + return 0; + } + + int autoLaunch = handle->getInt(InfoTableField::AUTO_LAUNCH); + handle->closeDB(); + + return autoLaunch; +} + +int web_provider_livebox_get_mouse_event(const char* box_id) +{ + if (!box_id) { + return 0; + } + + std::shared_ptr<WebProviderDB> handle(new WebProviderDB()); + if (!handle->openDB()) { + return 0; + } + + std::string query = "select * from " + infoTable + " where box_id = ?"; + if (!handle->setCommand(query, "s", box_id)) { + handle->closeDB(); + return 0; + } + + if (!handle->executeCommand()) { + handle->closeDB(); + return 0; + } + + int mouseEvent = handle->getInt(InfoTableField::MOUSE_EVENT); + handle->closeDB(); + + return mouseEvent; +} + +int web_provider_livebox_get_pd_fast_open(const char* box_id) +{ + if (!box_id) { + return 0; + } + + std::shared_ptr<WebProviderDB> handle(new WebProviderDB()); + if (!handle->openDB()) { + return 0; + } + + std::string query = "select * from " + infoTable + " where box_id = ?"; + if (!handle->setCommand(query, "s", box_id)) { + handle->closeDB(); + return 0; + } + + if (!handle->executeCommand()) { + handle->closeDB(); + return 0; + } + + int pdFastOpen = handle->getInt(InfoTableField::PD_FAST_OPEN); + handle->closeDB(); + + return pdFastOpen; +} + +int web_provider_livebox_insert_box_info( + const char* box_id, + const char* app_id, + const char* box_type, + int auto_launch, + int mouse_event, + int pd_fast_open) +{ + if (!box_id || !app_id || !box_type) { + return -1; + } + + std::shared_ptr<WebProviderDB> handle(new WebProviderDB()); + if (!handle->openDB()) { + return -1; + } + + std::string query = + "insert into " + infoTable + + " (box_id, app_id, box_type, auto_launch, mouse_event, pd_fast_open) \ + values (?,?,?,?,?,?)"; + + if (!handle->setCommand( + query, "sssiii", + box_id, app_id, box_type, auto_launch, mouse_event, pd_fast_open)) { + handle->closeDB(); + return -1; + } + + if (!handle->executeCommand()) { + handle->closeDB(); + return -1; + } + + handle->closeDB(); + return 0; +} + +int web_provider_livebox_delete_by_box_id(const char* box_id) +{ + if (!box_id) { + return -1; + } + + std::shared_ptr<WebProviderDB> handle(new WebProviderDB()); + if (!handle->openDB()) { + return -1; + } + + std::string query = + "delete from " + infoTable + " where box_id=?"; + + if (!handle->setCommand(query, "s", box_id)) { + handle->closeDB(); + return -1; + } + + if (!handle->executeCommand()) { + handle->closeDB(); + return -1; + } + + handle->closeDB(); + return 0; +} + +int web_provider_livebox_delete_by_app_id(const char* app_id) +{ + if (!app_id) { + return -1; + } + + std::shared_ptr<WebProviderDB> handle(new WebProviderDB()); + if (!handle->openDB()) { + return -1; + } + + std::string query = + "delete from " + infoTable + " where app_id=?"; + + if (!handle->setCommand(query, "s", app_id)) { + handle->closeDB(); + return -1; + } + + if (!handle->executeCommand()) { + handle->closeDB(); + return -1; + } + + handle->closeDB(); + return 0; +} + +int web_provider_livebox_delete_by_type(const char* type) +{ + if (!type) { + return -1; + } + + std::shared_ptr<WebProviderDB> handle(new WebProviderDB()); + if (!handle->openDB()) { + return -1; + } + + std::string query = + "delete from " + infoTable + " where type=?"; + + if (!handle->setCommand(query, "s", type)) { + handle->closeDB(); + return -1; + } + + if (!handle->executeCommand()) { + handle->closeDB(); + return -1; + } + + handle->closeDB(); + return 0; +} diff --git a/src_mobile/API/web_provider_livebox_info.h b/src_mobile/API/web_provider_livebox_info.h new file mode 100644 index 0000000..3cf1c41 --- /dev/null +++ b/src_mobile/API/web_provider_livebox_info.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file web_provider_livebox_info.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef WEB_PROVIDER_LIVEBOX_INFO_H +#define WEB_PROVIDER_LIVEBOX_INFO_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef EXPORT_API +#define EXPORT_API __attribute__((visibility("default"))) +#endif + +#define DEPRECATED_API __attribute__((visibility("default"))) __attribute__((deprecated)) + +/* TODO doxygen comments are needed to each exported API */ + +EXPORT_API const char* web_provider_livebox_get_default_type(); +EXPORT_API const char* web_provider_livebox_get_box_type(const char* box_id); +EXPORT_API const char* web_provider_livebox_get_app_id(const char* box_id); +EXPORT_API int web_provider_livebox_get_auto_launch(const char* box_id); +EXPORT_API int web_provider_livebox_get_mouse_event(const char* box_id); +EXPORT_API int web_provider_livebox_get_pd_fast_open(const char* box_id); +EXPORT_API int web_provider_livebox_insert_box_info( + const char* box_id, + const char* app_id, + const char* box_type, + int auto_launch, + int mouse_event, + int pd_fast_open); +EXPORT_API int web_provider_livebox_delete_by_box_id(const char* box_id); +EXPORT_API int web_provider_livebox_delete_by_app_id(const char* app_id); +EXPORT_API int web_provider_livebox_delete_by_type(const char* type); + +#ifdef __cplusplus +} +#endif +#endif //WEB_PROVIDER_LIVEBOX_INFO_H diff --git a/src_mobile/API/web_provider_plugin_info.cpp b/src_mobile/API/web_provider_plugin_info.cpp new file mode 100755 index 0000000..373c95f --- /dev/null +++ b/src_mobile/API/web_provider_plugin_info.cpp @@ -0,0 +1,350 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file web_provider_livebox_info.cpp + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ + + +#include <sys/stat.h> +#include <sys/types.h> +#include <dirent.h> +#include <string> +#include <cstring> +#include <cstdlib> +#include <list> +#include <glib.h> +#include <glib-object.h> +#include <json-glib/json-glib.h> +#include <Core/Util/Log.h> +#include "web_provider_livebox_info.h" +#include "web_provider_plugin_info.h" +#include <memory> + +// static functions +static web_provider_plugin_info* get_parsed_json_data(std::string& configPath); +static bool web_provider_plugin_release_info(web_provider_plugin_info* info); + +static const std::string installedPluginDirPath("/usr/lib/web-provider/"); + +// Json's content for plugin is the following (example) +// { +// "type" : "clip", +// "path" : "/usr/lib/web-provider/libweb-provider-plugin-clipbox.so", +// "service_boxid" : "org.tizen.browser" +// } +// +// "service_boxid" is only optional member in json file + +static const std::string jsonMemberType("type"); +static const std::string jsonMemberPath("path"); +static const std::string jsonMemberBoxId("service_boxid"); +static const std::string jsonMemberBoxScrollable("box_scrollable"); +static const std::string jsonMemberBoxSize("supported_size"); + +static const std::string jsonValueBoolTrue("true"); +static const std::string jsonValueBoolFalse("false"); +static const std::string jsonFileExtension(".json"); +static const std::string mandatoryBoxSize("1x1"); + +web_provider_plugin_info** web_provider_plugin_get_installed_list(int* count) +{ + LogD("enter"); + + // open directory of web provider plugin + DIR* dir = opendir(installedPluginDirPath.c_str()); + if (!dir) { + LogD("failed to open directory for web livebox plugins"); + *count = 0; + return NULL; + } + + // read plugin directory and store plugin config path + std::list<std::string> configList; + struct dirent* entry; + struct stat configStat; + std::string configPath; + while ((entry = readdir(dir))) { + if ((!strcmp(entry->d_name, ".")) || (!strcmp(entry->d_name, ".."))) { + continue; + } + + configPath = installedPluginDirPath + entry->d_name; + + if (stat(configPath.c_str(), &configStat) < 0) { + LogD("Failed to open file"); + continue; + } + + if (S_ISDIR(configStat.st_mode)) { + continue; + } + + if (configPath.substr(configPath.find_last_of(".")) == jsonFileExtension) { + LogD("config file: %s", configPath.c_str()); + configList.push_back(configPath); + } + } + // close directory of web provider plugin + closedir(dir); + + if (configList.size() == 0) { + *count = 0; + return NULL; + } + + // parse available each plugin json file + std::list<web_provider_plugin_info*> pluginList; + for (auto it = configList.begin(); + it != configList.end(); it++) { + web_provider_plugin_info* info = get_parsed_json_data(*it) ; + if (!info) { + continue; + } + + pluginList.push_back(info); + } + *count = pluginList.size(); + LogD("read plugin count: %d", *count); + + // c style array allocation for return of result + web_provider_plugin_info** info_list = + static_cast<web_provider_plugin_info**>( + malloc((*count) * sizeof(web_provider_plugin_info*))); + + // copy from members in std::list to one in c style array + int idx = 0; + for (auto it = pluginList.begin(); + it != pluginList.end(); it++) { + LogD("type: %s", (*it)->type); + LogD("path: %s", (*it)->path); + if ((*it)->service_boxid) { + LogD("service_boxid: %s", (*it)->service_boxid); + } + info_list[idx] = *it; + idx++; + } + + LogD("success to return plugin information"); + return info_list; +} + +void web_provider_plugin_release_installed_list( + web_provider_plugin_info** info_list, + int count) +{ + if (!info_list) { + return; + } + + for (int i = 0; i < count; i++) { + web_provider_plugin_release_info(info_list[i]); + } +} + +int web_provider_plugin_get_box_scrollable(const char* plugin_type) +{ + if (!plugin_type) { + return -1; + } + + std::string configPath; + configPath = installedPluginDirPath; + configPath += plugin_type; + configPath += jsonFileExtension; + web_provider_plugin_info* info = get_parsed_json_data(configPath); + + if (!info) { + return -1; + } + int ret = info->box_scrollable; + web_provider_plugin_release_info(info); + + LogD("box_scrollable: %d", ret); + return ret; +} + +static web_provider_plugin_info* get_parsed_json_data(std::string& configPath) +{ + g_type_init(); + + web_provider_plugin_info* info; + JsonParser* parser = json_parser_new(); + GError* error = NULL; + + if (!json_parser_load_from_file(parser, configPath.c_str(), &error)) { + LogD("failed to parse json file: %s -> %s", configPath.c_str(), error->message); + g_error_free(error); + g_object_unref(parser); + return NULL; + } + + JsonNode* root = json_parser_get_root(parser); + JsonObject* object = json_node_get_object(root); + + // check if type member exists on this json file + const char* type = + static_cast<const char*>( + json_object_get_string_member(object, jsonMemberType.c_str())); + + const char* path = + static_cast<const char*>( + json_object_get_string_member(object, jsonMemberPath.c_str())); + + JsonArray* size = + json_object_get_array_member(object, jsonMemberBoxSize.c_str()); + int sizeCount = static_cast<int>(json_array_get_length(size)); + + if (!type || !path || !sizeCount) { + LogD("mandatory members don't exist"); + g_error_free(error); + g_object_unref(parser); + return NULL; + } + + // allocate instance of plugin info struct + info = static_cast<web_provider_plugin_info*>( + malloc(sizeof(web_provider_plugin_info))); + memset(info, 0, sizeof(web_provider_plugin_info)); + + info->type = strdup(type); + info->path = strdup(path); + info->box_size = static_cast<char**>(malloc(sizeof(char*) * sizeCount)); + + for (int i = 0; i < sizeCount; i++) { + info->box_size[i] = + strdup(static_cast<const char*>(json_array_get_string_element(size, i))); + } + info->box_size_count = sizeCount; + + gboolean hasBoxId = json_object_has_member(object, jsonMemberBoxId.c_str()); + if (hasBoxId == TRUE) { + const char* boxId = + static_cast<const char*>( + json_object_get_string_member(object, jsonMemberBoxId.c_str())); + if (boxId) { + info->service_boxid = strdup(boxId); + } + } + + gboolean hasBoxScrollable = + json_object_has_member(object, jsonMemberBoxScrollable.c_str()); + if (hasBoxScrollable == TRUE) { + const char* boxScrollable = + static_cast<const char*>( + json_object_get_string_member(object, jsonMemberBoxScrollable.c_str())); + if (boxScrollable && (jsonValueBoolTrue == boxScrollable)) { + info->box_scrollable = 1; + } else { + info->box_scrollable = 0; + } + } + + LogD("type: %s", info->type); + LogD("path: %s", info->path); + if (info->service_boxid) { + LogD("service_boxid: %s", info->service_boxid); + } + LogD("box_scrollable: %d", info->box_scrollable); + + json_node_free(root); + g_error_free(error); + g_object_unref(parser); + + return info; +} + +bool web_provider_plugin_release_info(web_provider_plugin_info* info) +{ + LogD("enter"); + if (!info) { + LogD("empty struct"); + return false; + } + + // only members with buffer are released + delete info->type; + delete info->path; + delete info->service_boxid; + for(int i = 0; i < info->box_size_count; i++) { + delete[] info->box_size[i]; + } + delete info; + + return true; +} + +int web_provider_plugin_check_supported_size( + const char* plugin_type, char** size, int sizeCount) +{ + // read plugin directory and store plugin config path + std::string configPath; + configPath = installedPluginDirPath; + configPath += plugin_type; + configPath += jsonFileExtension; + + // get the json datas + web_provider_plugin_info* jsonData = get_parsed_json_data(configPath); + if (!jsonData) { + LogD("failed to get the json file"); + return false; + } + + // check if this type is default type + bool isDefaultType = false; + const char* defaultType = web_provider_livebox_get_default_type(); + if (!defaultType) { + LogD("can't get default type"); + return false; + } + if (!strcmp(plugin_type, defaultType)) { + isDefaultType = true; + } + + // compare the parsed config data with the parsed json data + bool mandatoryCheck = false; + for (int configCnt = 0; configCnt < sizeCount; configCnt++) { + bool supportedSizeCheck = false; + for (int jsonCnt = 0; jsonCnt < jsonData->box_size_count; jsonCnt++) { + + // check mandatory size + if (isDefaultType && !strcmp(mandatoryBoxSize.c_str(), size[configCnt])) { + mandatoryCheck = true; + } + + // check supported size + if (!strcmp(jsonData->box_size[jsonCnt], size[configCnt])) { + supportedSizeCheck = true; + break; + } + } + + if (!supportedSizeCheck) { + LogD("Not supported size: %s", size[configCnt]); + web_provider_plugin_release_info(jsonData); + return false; + } + } + + //release the jsonData + web_provider_plugin_release_info(jsonData); + if (isDefaultType && !mandatoryCheck) { + LogD("Mandatory members don't exist "); + return false; + } + + return true; +} diff --git a/src_mobile/API/web_provider_plugin_info.h b/src_mobile/API/web_provider_plugin_info.h new file mode 100755 index 0000000..612497c --- /dev/null +++ b/src_mobile/API/web_provider_plugin_info.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file web_provider_plugin_info.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef WEB_PROVIDER_PLUGIN_INFO_H +#define WEB_PROVIDER_PLUGIN_INFO_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef EXPORT_API +#define EXPORT_API __attribute__((visibility("default"))) +#endif + +struct _web_provider_plugin_info { + const char* type; + const char* path; + const char* service_boxid; + char** box_size; + int box_scrollable; + int box_size_count; +}; +typedef _web_provider_plugin_info web_provider_plugin_info; + +EXPORT_API web_provider_plugin_info** web_provider_plugin_get_installed_list( + int* count); +EXPORT_API void web_provider_plugin_release_installed_list( + web_provider_plugin_info** info_list, + int count); +EXPORT_API int web_provider_plugin_get_box_scrollable(const char* plugin_type); +EXPORT_API int web_provider_plugin_check_supported_size(const char* plugin_type, char** size, int sizeCount); +#ifdef __cplusplus +} +#endif +#endif //WEB_PROVIDER_PROVIDER_INFO_H diff --git a/src_mobile/CMakeLists.txt b/src_mobile/CMakeLists.txt new file mode 100644 index 0000000..0a978b0 --- /dev/null +++ b/src_mobile/CMakeLists.txt @@ -0,0 +1,31 @@ +# Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved +# +# Licensed under the Flora License, Version 1.1 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://floralicense.org/license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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) + +SET(TARGET_API web-provider-api) +SET(TARGET_CORE web-provider-core) +SET(TARGET_DAEMON web-provider) +SET(TARGET_PLUGIN web-provider-plugin) + +INCLUDE_DIRECTORIES( + ${CMAKE_CURRENT_SOURCE_DIR}/API + ${CMAKE_CURRENT_SOURCE_DIR}/Core + ${CMAKE_CURRENT_SOURCE_DIR}/Plugin +) + +ADD_SUBDIRECTORY(API) +ADD_SUBDIRECTORY(Core) +ADD_SUBDIRECTORY(Daemon) +ADD_SUBDIRECTORY(Plugin) diff --git a/src_mobile/Core/Box.cpp b/src_mobile/Core/Box.cpp new file mode 100644 index 0000000..8d502c8 --- /dev/null +++ b/src_mobile/Core/Box.cpp @@ -0,0 +1,387 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file Box.cpp + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#include <string> +#include <Ecore.h> +#include <Plugin/IBoxPluginFactory.h> +#include "Buffer/IRenderBuffer.h" +#include "Buffer/RenderBuffer.h" +#include "Buffer/RenderBufferFactory.h" +#include "Util/Log.h" +#include "Util/Util.h" +#include "BoxData.h" +#include "IBoxState.h" +#include "BoxState.h" +#include "Util/ITimer.h" +#include "BoxUpdateTimer.h" +#include "BoxSchemeHandler.h" +#include "Box.h" + +// This is used for informing context of box to web content as value of url parameter +static const std::string renderTypeCreate("create"); +static const std::string renderTypeResize("resize"); +static const std::string renderTypeOpenPd("pdopen"); +static const std::string renderTypeUpdate("update"); + +Box::Box(BoxInfoPtr boxInfo, IBoxPluginFactoryPtr factory, EwkContextPtr ewkContext) + : m_boxInfo(boxInfo) + , m_factory(factory) + , m_currentTab(true) + , m_paused(false) + , m_updateNeeded(false) + , m_lastUpdateRequestTime() +{ + LogD("enter"); + try { + m_boxBuffer = m_factory->createBoxRenderBuffer( + boxInfo->boxId, + boxInfo->instanceId, + boxInfo->boxWidth, + boxInfo->boxHeight, + boxInfo->contentInfo); + m_boxBuffer->allocate(); + m_view = m_factory->createRenderView( + boxInfo->boxId, + boxInfo->instanceId, + ewkContext); + m_updateTimer = BoxUpdateTimer::create( + boxInfo->period, + Box::updateCallback, + this); + BoxSchemeHandler::Instance()->registerBox(boxInfo->instanceId, this); + + // TODO code regarding state needs more testing + //m_state = BoxInitState::create( + // IBoxContextPtr(dynamic_cast<IBoxContext*>(this))); + } catch (...) { + throw; + } +} + +Box::~Box() +{ + LogD("enter"); + BoxSchemeHandler::Instance()->unregisterBox(m_boxInfo->instanceId); +} + +bool Box::show() +{ + LogD("enter"); + CHECK_BOX_STATE(m_state, permitShow); + + try { + m_updateTimer->start(); + RenderInfoPtr renderInfo = makeRenderInfo(renderTypeCreate, URL_TYPE_BOX); + m_view->showBox(renderInfo); + } catch (...) { + return false; + } + + SWITCH_BOX_STATE(); + return true; +} + +bool Box::hide() +{ + LogD("enter"); + CHECK_BOX_STATE(m_state, permitHide); + + try { + if (m_pdBuffer) { + m_pdBuffer->stopCanvasUpdate(); + m_view->hidePd(); + m_pdBuffer->free(); + m_pdBuffer.reset(); + } + + m_updateTimer->stop(); + m_boxBuffer->stopCanvasUpdate(); + m_view->hideBox(); + m_boxBuffer->free(); + m_boxBuffer.reset(); + } catch (...) { + return false; + } + + SWITCH_BOX_STATE(); + return true; +} + +bool Box::resize(int width, int height) +{ + LogD("enter"); + CHECK_BOX_STATE(m_state, permitShow); + + // reset box info to new width, height + m_boxInfo->boxWidth = width; + m_boxInfo->boxHeight = height; + + try { + m_updateTimer->restart(); + m_boxBuffer->reallocate( + m_boxInfo->boxWidth, m_boxInfo->boxHeight); + RenderInfoPtr renderInfo = makeRenderInfo(renderTypeResize, URL_TYPE_BOX); + m_view->showBox(renderInfo); + } catch (...) { + LogD("resize exception"); + return false; + } + + SWITCH_BOX_STATE(); + return true; +} + +bool Box::resume() +{ + LogD("enter"); + CHECK_BOX_STATE(m_state, permitResume); + + try { + m_currentTab = true; + m_paused = false; + + if (m_updateNeeded) { + m_updateNeeded = false; + updateInternal(); + } else { + m_view->resumeBox(); + } + } catch (...) { + return false; + } + + SWITCH_BOX_STATE(); + return true; +} + +bool Box::pause(bool background) +{ + LogD("enter"); + CHECK_BOX_STATE(m_state, permitPause); + + try { + if (!background) { + m_currentTab = false; + } + m_paused = true; + m_view->pauseBox(); + } catch (...) { + return false; + } + + SWITCH_BOX_STATE(); + return true; +} + +bool Box::openPd(int width, int height, double x, double y) +{ + LogD("enter"); + CHECK_BOX_STATE(m_state, permitOpenPd); + + m_boxInfo->pdWidth = width; + m_boxInfo->pdHeight = height; + m_boxInfo->pdX = x; + m_boxInfo->pdY = y; + + try { + m_updateTimer->stop(); + m_pdBuffer = RenderBufferFactory::create( + RenderBufferFactory::RENDER_BUFFER_TYPE_PD, + m_boxInfo->boxId, + m_boxInfo->instanceId, + m_boxInfo->pdWidth, + m_boxInfo->pdHeight); + m_pdBuffer->allocate(); + m_pdBuffer->stopCanvasUpdate(); + RenderInfoPtr pdRenderInfo = makeRenderInfo(renderTypeOpenPd, URL_TYPE_PD); + RenderInfoPtr boxRenderInfo = makeRenderInfo(renderTypeOpenPd, URL_TYPE_BOX); + m_view->showPd(pdRenderInfo, boxRenderInfo); + ecore_idler_add(startUpdateRenderBufferIdlerCallback, m_pdBuffer.get()); + } catch (...) { + return false; + } + + SWITCH_BOX_STATE(); + return true; +} + +bool Box::closePd() +{ + LogD("enter"); + CHECK_BOX_STATE(m_state, permitClosePd); + + try { + if (m_pdBuffer) { + m_pdBuffer->stopCanvasUpdate(); + m_view->hidePd(); + m_pdBuffer->free(); + m_pdBuffer.reset(); + } + m_updateTimer->restart(); + } catch (...) { + return false; + } + + // if box update is requested during pd opening + if (m_updateNeeded) { + updateInternal(); + } + + SWITCH_BOX_STATE(); + return true; +} + +bool Box::update(time_t requestTime, std::string& contentInfo) +{ + LogD("enter"); + + m_lastUpdateRequestTime = requestTime; + m_boxInfo->contentInfo = contentInfo; + if (m_paused || m_pdBuffer) { + // update is dalayed + // until this box goes to current tab or pd is closed + m_updateNeeded = true; + return true; + } + + try { + updateInternal(); + } catch (...) { + return false; + } + + return true; +} + +bool Box::changePeriod(float period) +{ + LogD("enter"); + + // reset period + m_boxInfo->period = period; + m_updateTimer->setPeriod(m_boxInfo->period); + + return true; +} + +bool Box::isCurrentTab() +{ + return m_currentTab; +} + +time_t Box::getLastUpdateRequestTime() +{ + return m_lastUpdateRequestTime; +} + +RenderInfoPtr Box::makeRenderInfo(const std::string& renderType, UrlType urlType) const +{ + LogD("enter"); + RenderInfoPtr renderInfo(new RenderInfo); + + // add width, height, operation type + renderInfo->defaultUrlParams = "?type=" + renderType; + + // set width, height + switch (urlType) { + case URL_TYPE_BOX: + renderInfo->window = m_boxBuffer->getWindow(); + renderInfo->width = m_boxInfo->boxWidth; + renderInfo->height = m_boxInfo->boxHeight; + break; + case URL_TYPE_PD: + renderInfo->window = m_pdBuffer->getWindow(); + renderInfo->width = m_boxInfo->pdWidth; + renderInfo->height = m_boxInfo->pdHeight; + break; + default: + LogD("error url type"); + return RenderInfoPtr(); + } + + char buff[32]; + sprintf(buff, "&width=%d&height=%d", renderInfo->width, renderInfo->height); + renderInfo->defaultUrlParams += buff; + + // if needed, set pd information + if (renderType == renderTypeOpenPd) { + renderInfo->defaultUrlParams += "&pdopen-direction="; + if (m_boxInfo->pdY == 0.0f) { + renderInfo->defaultUrlParams += "down"; + } else { + renderInfo->defaultUrlParams += "up"; + } + + char buff[32]; + sprintf(buff, "&pdopen-arrow-xpos=%d", + static_cast<int>((m_boxInfo->pdX) * (m_boxInfo->pdWidth))); + renderInfo->defaultUrlParams += buff; + } + + + // add content info + if (!m_boxInfo->contentInfo.empty()) { + renderInfo->defaultUrlParams += "&" + m_boxInfo->contentInfo; + } + + LogD("default url param string: %s", renderInfo->defaultUrlParams.c_str()); + return renderInfo; +} + +void Box::updateInternal() +{ + LogD("enter"); + RenderInfoPtr renderInfo = makeRenderInfo(renderTypeUpdate, URL_TYPE_BOX); + m_view->showBox(renderInfo); +} + +void Box::setState(IBoxStatePtr state) +{ + UNUSED_PARAM(state); + // assign new state + //m_state = state; +} + +Eina_Bool Box::updateCallback(void* data) +{ + LogD("enter"); + Box* This = static_cast<Box*>(data); + + This->updateInternal(); + return ECORE_CALLBACK_RENEW; +} + +Eina_Bool Box::startUpdateRenderBufferIdlerCallback(void* data) +{ + LogD("enter"); + RenderBuffer* buffer = static_cast<RenderBuffer*>(data); + if (!buffer) { + LogD("no buffer"); + } else { + buffer->startCanvasUpdate(); + } + + return ECORE_CALLBACK_CANCEL; +} + +BoxInfoPtr Box::getBoxInfo() +{ + LogD("enter"); + return m_boxInfo; +} diff --git a/src_mobile/Core/Box.h b/src_mobile/Core/Box.h new file mode 100644 index 0000000..33eaf17 --- /dev/null +++ b/src_mobile/Core/Box.h @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file Box.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef BOX_H +#define BOX_H + +#include <string> +#include <memory> +#include <ctime> +#include <Ecore.h> +#include <Plugin/IBoxPluginFactory.h> +#include "Buffer/IRenderBuffer.h" +#include "View/IRenderView.h" +#include "Util/ITimer.h" +#include "BoxData.h" +#include "IBoxState.h" +#include "IBoxContext.h" +#include "IBox.h" +#include "Box.h" + +class Box: public IBox, public IBoxContext { + public: + static IBoxPtr create( + BoxInfoPtr boxInfo, + IBoxPluginFactoryPtr factory, + EwkContextPtr ewkContext) + { + return IBoxPtr(new Box(boxInfo, factory, ewkContext)); + }; + // IBox + bool show(); + bool hide(); + bool resize(int width, int height); + bool resume(); + bool pause(bool background); + bool openPd(int width, int height, double x, double y); + bool closePd(); + bool update(time_t requestTime, std::string& contentInfo); + bool changePeriod(float period); + bool isCurrentTab(); + time_t getLastUpdateRequestTime(); + BoxInfoPtr getBoxInfo(); + + ~Box(); + + private: + enum UrlType { + URL_TYPE_BOX = 0, + URL_TYPE_PD + }; + + RenderInfoPtr makeRenderInfo(const std::string& renderType, UrlType urlType) const; + void updateInternal(); + + // IBoxContext + void setState(IBoxStatePtr state); + + // static callbacks + static Eina_Bool updateCallback(void* data); + static Eina_Bool startUpdateRenderBufferIdlerCallback(void* data); + + // constructor + explicit Box( + BoxInfoPtr boxInfo, + IBoxPluginFactoryPtr factory, + EwkContextPtr ewkContext); + + BoxInfoPtr m_boxInfo; + IBoxPluginFactoryPtr m_factory; + IRenderBufferPtr m_boxBuffer; + IRenderBufferPtr m_pdBuffer; + IRenderViewPtr m_view; + ITimerPtr m_updateTimer; + //IBoxStatePtr m_state; + // flag for knowing this box is on current tab + bool m_currentTab; + // flag for knowing this box has been already paused + bool m_paused; + // flag for knowing this box should be updated when the box is resumed + bool m_updateNeeded; + // timestamp for saving last update request from external app + time_t m_lastUpdateRequestTime; + + friend class BoxSchemeHandler; +}; + +#endif //BOX_H + diff --git a/src_mobile/Core/BoxData.h b/src_mobile/Core/BoxData.h new file mode 100644 index 0000000..86bdfb4 --- /dev/null +++ b/src_mobile/Core/BoxData.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file BoxData.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef BOX_DATA_H +#define BOX_DATA_H + +#include <memory> +#include <string> + +struct BoxInfo +{ + std::string boxType; + std::string boxId; + std::string instanceId; + int boxWidth; + int boxHeight; + int pdWidth; + int pdHeight; + double pdX; + double pdY; + int priority; + float period; + std::string contentInfo; + + // initialization + BoxInfo(std::string boxType, + std::string boxId, + std::string instanceId) : + boxType(boxType), + boxId(boxId), + instanceId(instanceId), + boxWidth(0), + boxHeight(0), + pdWidth(0), + pdHeight(0), + pdX(0.0f), + pdY(0.0f), + priority(0), + period(0), + contentInfo() + { + }; + + BoxInfo() : + boxType(), + boxId(), + instanceId(), + boxWidth(0), + boxHeight(0), + pdWidth(0), + pdHeight(0), + pdX(0.0f), + pdY(0.0f), + priority(0), + period(0), + contentInfo() + { + }; +}; + +typedef std::shared_ptr<struct BoxInfo> BoxInfoPtr; +typedef struct BoxInfo& BoxInfoRef; + +#endif // BOX_DATA_H diff --git a/src_mobile/Core/BoxManager.cpp b/src_mobile/Core/BoxManager.cpp new file mode 100644 index 0000000..a4307b4 --- /dev/null +++ b/src_mobile/Core/BoxManager.cpp @@ -0,0 +1,327 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file BoxManager.cpp + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#include <string> +#include <map> +#include <ctime> +#include <ewk_context.h> +#include <Plugin/IBoxPluginFactory.h> +#include <Plugin/box_plugin_interface.h> +#include "Util/Log.h" +#include "Util/Util.h" +#include "IBox.h" +#include "Box.h" +#include "BoxData.h" +#include "BoxManager.h" + +BoxManager::BoxManager(IBoxPluginFactoryPtr factory) + : m_boxFactory(factory) +{ + LogD("enter"); +} + +BoxManager::~BoxManager() +{ + LogD("enter"); +} + +bool BoxManager::doCommand(const request_cmd_type type, const BoxInfoPtr& boxInfo) +{ + bool result = false; + + switch (type) { + case REQUEST_CMD_ADD_BOX: + result = requestAddBox(boxInfo, m_defaultContext); + break; + case REQUEST_CMD_REMOVE_BOX: + result = requestRemoveBox(boxInfo->instanceId); + break; + case REQUEST_CMD_RESIZE_BOX: + result = requestResizeBox(boxInfo->instanceId, boxInfo->boxWidth, boxInfo->boxHeight); + break; + case REQUEST_CMD_RESUME_BOX: + result = requestResumeBox(boxInfo->instanceId); + break; + case REQUEST_CMD_PAUSE_BOX: + result = requestPauseBox(boxInfo->instanceId); + break; + case REQUEST_CMD_RESUME_ALL: + result = requestResumeAll(); + break; + case REQUEST_CMD_PAUSE_ALL: + result = requestPauseAll(); + break; + case REQUEST_CMD_OPEN_PD: + result = requestOpenPd(boxInfo->instanceId, + boxInfo->pdWidth, boxInfo->pdHeight, + boxInfo->pdX, boxInfo->pdY); + break; + case REQUEST_CMD_CLOSE_PD: + result = requestClosePd(boxInfo->instanceId); + break; + case REQUEST_CMD_CHANGE_PERIOD: + result = requestChangePeriod(boxInfo->instanceId, boxInfo->period); + break; + case REQUEST_CMD_UPDATE_BOX: + result = requestUpdateBox(boxInfo->boxId, boxInfo->contentInfo); + break; + case REQUEST_CMD_CHANGE_LANGUAGE: + result = requestChangeLanguage(boxInfo->instanceId); + break; + default: + LogD("not available request type"); + break; + } + + return result; +} + +bool BoxManager::requestAddBox(BoxInfoPtr boxInfo, EwkContextPtr ewkContext) +{ + IBoxPtr box; + + // create new box + try { + if (!ewkContext) { + if (!m_defaultContext) { + m_defaultContext = EwkContextPtr(ewk_context_new(), EwkContextDeleter()); + } + ewkContext = m_defaultContext; + } + box = Box::create(boxInfo, m_boxFactory, ewkContext); + } catch (...) { + LogD("exection occurs during adding box"); + return false; + } + + // show new box + if (!box->show()) { + LogD("problem occurs during rendering box"); + return false; + } + + insertBoxMap(boxInfo->instanceId, box); + return true; +} + +bool BoxManager::requestRemoveBox(std::string& instanceId) +{ + IBoxPtr box = searchBoxMap(instanceId); + if (!box) { + return false; + } + + if (!box->hide()) { + return false; + } + + eraseBoxMap(instanceId); + return true; +} + +bool BoxManager::requestResizeBox(std::string& instanceId, int width, int height) +{ + LogD("enter"); + IBoxPtr box = searchBoxMap(instanceId); + if (!box) { + return false; + } + + return box->resize(width, height); +} + +bool BoxManager::requestResumeBox(std::string& instanceId) +{ + LogD("enter"); + IBoxPtr box = searchBoxMap(instanceId); + if (!box) { + return false; + } + + return box->resume(); +} + +bool BoxManager::requestPauseBox(std::string& instanceId) +{ + LogD("enter"); + IBoxPtr box = searchBoxMap(instanceId); + if (!box) { + return false; + } + + // paused by switching other page + return box->pause(false); +} + +bool BoxManager::requestResumeAll() +{ + LogD("enter"); + for (auto it = m_boxMap.begin(); it != m_boxMap.end(); it++) { + if (it->second->isCurrentTab()) { + it->second->resume(); + } + } + + return true; +} + +bool BoxManager::requestPauseAll() +{ + LogD("enter"); + for (auto it = m_boxMap.begin(); it != m_boxMap.end(); it++) { + if (it->second->isCurrentTab()) { + // paused by entering background + it->second->pause(true); + } + } + + return true; +} + +bool BoxManager::requestOpenPd( + std::string& instanceId, + int width, int height, double x, double y) +{ + LogD("enter"); + IBoxPtr box = searchBoxMap(instanceId); + if (!box) { + return false; + } + + return box->openPd(width, height, x, y); +} + +bool BoxManager::requestClosePd(std::string& instanceId) +{ + LogD("enter"); + IBoxPtr box = searchBoxMap(instanceId); + if (!box) { + return false; + } + + return box->closePd(); +} + +bool BoxManager::requestChangePeriod(std::string& instanceId, float period) +{ + LogD("enter"); + IBoxPtr box = searchBoxMap(instanceId); + if (!box) { + return false; + } + + return box->changePeriod(period); +} + +bool BoxManager::requestUpdateBox(std::string& boxId, std::string& contentInfo) +{ + LogD("enter"); + + IBoxPtr box; + box.reset(); + + time_t requestTime = time(NULL); + + for (auto it = m_boxMap.begin(); it != m_boxMap.end(); ++it) { + if (it->first.find(boxId) == std::string::npos) { + continue; + } + box = it->second; + box->update(requestTime, contentInfo); + } + + return true; +} + +bool BoxManager::requestChangeLanguage(std::string& instanceId) +{ + LogD("enter"); + UNUSED_PARAM(instanceId); + + IBoxPtr box; + box.reset(); + + time_t requestTime = time(NULL); + + for (auto it = m_boxMap.begin(); it != m_boxMap.end(); ++it) { + if (it->second) { + box = it->second; + box->update(requestTime, box->getBoxInfo()->contentInfo); + } + } + return true; +} + +void BoxManager::insertBoxMap(std::string& instanceId, IBoxPtr box) +{ + if (!searchBoxMap(instanceId)) { + LogD("insert box to map: %s", instanceId.c_str()); + m_boxMap.insert(BoxMapPair(instanceId, box)); + } else { + LogD("this box was already inserted!"); + } +} + +void BoxManager::eraseBoxMap(std::string& instanceId) +{ + LogD("erase box to map"); + if (!searchBoxMap(instanceId)) { + LogD("not available box"); + return; + } + + m_boxMap.erase(instanceId); +} + +void BoxManager::updateBoxMap(std::string& instanceId, IBoxPtr box) +{ + if (searchBoxMap(instanceId)) { + eraseBoxMap(instanceId); + } + + insertBoxMap(instanceId, box); +} + +IBoxPtr BoxManager::searchBoxMap(std::string& instanceId) +{ + LogD("enter"); + IBoxPtr box; + box.reset(); + auto it = m_boxMap.find(instanceId); + if (it != m_boxMap.end()) { + LogD("found box: %s (%p)", it->first.c_str(), it->second.get()); + box = it->second; + } + + return box; +} + +void BoxManager::clearBoxMap() +{ + m_boxMap.clear(); +} + +void BoxManager::EwkContextDeleter::operator()(Ewk_Context* ptr) +{ + LogD("ewk context delete"); + if (ptr) { + ewk_context_delete(ptr); + } +} + diff --git a/src_mobile/Core/BoxManager.h b/src_mobile/Core/BoxManager.h new file mode 100644 index 0000000..77806bb --- /dev/null +++ b/src_mobile/Core/BoxManager.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file BoxManager.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef BOX_MANAGER_H +#define BOX_MANAGER_H + +#include <map> +#include <string> +#include <memory> +#include <Plugin/box_plugin_interface.h> +#include <Plugin/IBoxPluginFactory.h> +#include "BoxData.h" +#include "IBox.h" +#include "IBoxManager.h" + +#define EXPORT_CLASS __attribute__ ((visibility("default")) + +class EXPORT_CLASS BoxManager: public IBoxManager { + public: + static IBoxManagerPtr create(IBoxPluginFactoryPtr factory) + { + return IBoxManagerPtr(new BoxManager(factory)); + }; + virtual bool doCommand(const request_cmd_type type, const BoxInfoPtr& boxInfo); + virtual ~BoxManager(); + + protected: + virtual bool requestAddBox(BoxInfoPtr boxInfo, EwkContextPtr ewkContext); + virtual bool requestRemoveBox(std::string& instanceId); + virtual bool requestResizeBox(std::string& instanceId, int width, int height); + virtual bool requestResumeBox(std::string& instanceId); + virtual bool requestPauseBox(std::string& instanceId); + virtual bool requestResumeAll(); + virtual bool requestPauseAll(); + virtual bool requestOpenPd( + std::string& instanceId, + int width, int height, double x, double y); + virtual bool requestClosePd(std::string& instanceId); + virtual bool requestChangePeriod(std::string& instanceId, float period); + virtual bool requestUpdateBox(std::string& boxId, std::string& contentInfo); + virtual bool requestChangeLanguage(std::string& instanceId); + + // ewk context deleter + struct EwkContextDeleter { + void operator()(Ewk_Context* ptr); + }; + + explicit BoxManager(IBoxPluginFactoryPtr factory); + + private: + // map operations + void insertBoxMap(std::string& instanceId, IBoxPtr box); + void eraseBoxMap(std::string& instanceId); + void updateBoxMap(std::string& instanceId, IBoxPtr box); + IBoxPtr searchBoxMap(std::string& instanceId); + void clearBoxMap(); + + typedef std::map<std::string, IBoxPtr> BoxMap; + typedef std::pair<std::string, IBoxPtr> BoxMapPair; + BoxMap m_boxMap; + IBoxPluginFactoryPtr m_boxFactory; + EwkContextPtr m_defaultContext; +}; + +#endif // BOX_MANAGER_H diff --git a/src_mobile/Core/BoxSchemeHandler.cpp b/src_mobile/Core/BoxSchemeHandler.cpp new file mode 100755 index 0000000..9e04704 --- /dev/null +++ b/src_mobile/Core/BoxSchemeHandler.cpp @@ -0,0 +1,308 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file BoxSchemeHandler.cpp + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ + +#include <string.h> +#include <ctime> +#include "Box.h" +#include "Service/AppControl.h" +#include "Service/PeriodChanger.h" +#include "Service/ScrollHolder.h" +#include "Service/MessageManager.h" +#include "Util/Log.h" +#include "Util/Util.h" +#include "BoxSchemeHandler.h" + +using namespace Service; + +static const std::string BOX_SCHEME("box://"); +static const std::string BOX_SCHEME_RELOAD("box://reload"); +static const std::string BOX_SCHEME_CHANGE_PERIOD("box://change-period"); +static const std::string BOX_SCHEME_LAUNCH_BROWSER("box://launch-browser"); +static const std::string BOX_SCHEME_SCROLL_START("box://scroll-start"); +static const std::string BOX_SCHEME_SCROLL_STOP("box://scroll-stop"); +static const std::string BOX_SCHEME_SEND_MESSAGE_TO_PD("box://send-message-to-pd"); +static const std::string BOX_SCHEME_SEND_MESSAGE_TO_BOX("box://send-message-to-box"); + +static const std::string HTTP_SCHEME("http://"); +static const std::string HTTPS_SCHEME("https://"); + +// static variable intialization +BoxSchemeHandler* BoxSchemeHandler::s_instance = NULL; + +BoxSchemeHandler::BoxSchemeHandler() + : m_boxMap() +{ + LogD("enter"); +} + +BoxSchemeHandler::~BoxSchemeHandler() +{ + LogD("enter"); +} + +BoxSchemeHandler* BoxSchemeHandler::Instance() +{ + LogD("enter"); + if (!s_instance) { + s_instance = new BoxSchemeHandler(); + } + + return s_instance; +} + +void BoxSchemeHandler::registerBox(std::string& instanceId, Box* box) +{ + LogD("enter"); + + if (getBox(instanceId)) { + LogD("already registered"); + return; + } + + m_boxMap.insert(BoxMapPair(instanceId, box)); +} + +void BoxSchemeHandler::unregisterBox(std::string& instanceId) +{ + LogD("enter"); + m_boxMap.erase(instanceId); +} + +bool BoxSchemeHandler::process(std::string& instanceId, std::string& uri) +{ + LogD("enter"); + + if (!isBoxScheme(uri)) { + return false; + } + + if (!uri.compare(BOX_SCHEME_RELOAD)) { + return handleReload(instanceId); + } + + if (!uri.compare( + 0, + BOX_SCHEME_CHANGE_PERIOD.size(), + BOX_SCHEME_CHANGE_PERIOD)) + { + std::string key("period"); + std::string period = parse(uri, key); + if (period.empty()) { + return handleChangePeriod(instanceId); + } + + return handleChangePeriod(instanceId, std::atof(period.c_str())); + } + + if (!uri.compare( + 0, + BOX_SCHEME_LAUNCH_BROWSER.size(), + BOX_SCHEME_LAUNCH_BROWSER)) + { + std::string key("url"); + std::string url = parse(uri, key); + return handleLaunchBrowser(instanceId, url); + } + + if (!uri.compare(BOX_SCHEME_SCROLL_START)) { + return handleScroll(instanceId, true); + } + + if (!uri.compare(BOX_SCHEME_SCROLL_STOP)) { + return handleScroll(instanceId, false); + } + + if (!uri.compare( + 0, + BOX_SCHEME_SEND_MESSAGE_TO_BOX.size(), + BOX_SCHEME_SEND_MESSAGE_TO_BOX)) + { + std::string key("message"); + std::string message = parse(uri, key); + return handleSendMessage(instanceId, MessageManager::TO_BOX, message); + } + + if (!uri.compare( + 0, + BOX_SCHEME_SEND_MESSAGE_TO_PD.size(), + BOX_SCHEME_SEND_MESSAGE_TO_PD)) + { + std::string key("message"); + std::string message = parse(uri, key); + return handleSendMessage(instanceId, MessageManager::TO_PD, message); + } + LogD("unknown box scheme protocol"); + return false; +} + +bool BoxSchemeHandler::isBoxScheme(std::string& uri) +{ + LogD("enter"); + if(!uri.compare(0, BOX_SCHEME.size(), BOX_SCHEME)) { + return true; + } + + return false; +} + +Box* BoxSchemeHandler::getBox(std::string& instanceId) +{ + LogD("enter"); + + auto it = m_boxMap.find(instanceId); + if (it != m_boxMap.end()) { + LogD("registered: %s (%p)", it->first.c_str(), it->second); + return it->second; + } + + return NULL; +} + +bool BoxSchemeHandler::handleScroll(std::string& instanceId, bool start) +{ + using namespace Service::ScrollHolder; + + LogD("enter"); + Box* box = getBox(instanceId); + if (!box) { + LogD("unregistered instance"); + return false; + } + + holdHorizontalScroll(box->m_boxInfo->boxId, instanceId, start); + return true; +} + +bool BoxSchemeHandler::handleReload(std::string& instanceId) +{ + LogD("enter"); + Box* box = getBox(instanceId); + if (!box) { + LogD("unregistered instance"); + return false; + } + + // In the future, new content info can be set by caller + box->updateInternal(); + return true; +} + +bool BoxSchemeHandler::handleChangePeriod(std::string& instanceId, double requestedPeriod) +{ + LogD("enter"); + + Box* box = getBox(instanceId); + if (!box) { + LogD("no box for update period"); + return false; + } + + if (Service::PeriodChanger::isPopupOpened()) { + LogD("preiod popup is already opened!"); + return false; + } + + m_periodChanger = + Service::PeriodChanger::create( + box->m_boxInfo->boxId, instanceId, + box->m_boxInfo->period, requestedPeriod); + + return m_periodChanger->change(); +} + +bool BoxSchemeHandler::handleLaunchBrowser(std::string& instanceId, std::string& url) +{ + LogD("enter"); + UNUSED_PARAM(instanceId); + + if (!url.compare(0, HTTP_SCHEME.size(), HTTP_SCHEME) || + !url.compare(0, HTTPS_SCHEME.size(), HTTPS_SCHEME)) + { + return Service::AppControl::launchBrowser(url); + } + + return false; +} + +bool BoxSchemeHandler::handleSendMessage( + std::string& instanceId, + MessageManager::ReceiverType receiver, + std::string& message) +{ + LogD("enter"); + Box* box = getBox(instanceId); + if (!box) { + LogD("no box for update period"); + return false; + }; + + // set webview of receiver + Evas_Object* webview; + switch (receiver) { + case MessageManager::TO_BOX: + webview = box->m_view->getBoxWebView(); + break; + case MessageManager::TO_PD: + webview = box->m_view->getPdWebView(); + break; + default: + LogD("not supported receiver"); + return false; + } + + return m_messageManager->send(webview, receiver, message); +} + +std::string BoxSchemeHandler::parse(std::string& uri, std::string& key) +{ + LogD("enter"); + + // TODO url parameter SHOULD be parsed using std::regex, not manually + std::string value(""); + + unsigned found = uri.find_first_of("?"); + if (found == std::string::npos) { + LogD("no query"); + return value; + } + + std::string query = std::string(uri, found + 1); + found = 0; + do { + LogD("enter\n"); + unsigned seperator = query.find_first_of("=", found + 1); + if (seperator == std::string::npos) { + LogD("no '=' character\n"); + break; + } + + unsigned next = query.find_first_of("@", found + 1); + if (!query.compare(found, key.size(), key)) { + LogD("key matched!\n"); + value = std::string(query, seperator + 1, next - seperator - 1); + break; + } + + found = next + 1; + } while (found && found != std::string::npos); + + LogD("URL query parsing result: key -> %s, value -> %s", key.c_str(), value.c_str()); + return value; +} diff --git a/src_mobile/Core/BoxSchemeHandler.h b/src_mobile/Core/BoxSchemeHandler.h new file mode 100755 index 0000000..f855196 --- /dev/null +++ b/src_mobile/Core/BoxSchemeHandler.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file BoxSchemeHandler.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef BOX_SCHEME_HANDLER_H +#define BOX_SCHEME_HANDLER_H + +#include <string> +#include <map> +#include "Service/PeriodChanger.h" +#include "Service/MessageManager.h" + +using namespace Service; + +class Box; + +#define EXPORT_CLASS __attribute__ ((visibility("default")) + +class EXPORT_CLASS BoxSchemeHandler { + public: + static BoxSchemeHandler* Instance(); + void registerBox(std::string& instanceId, Box* box); + void unregisterBox(std::string& instanceId); + bool process(std::string& instanceId, std::string& uri); + bool isBoxScheme(std::string& uri); + + private: + Box* getBox(std::string& instanceId); + bool handleReload(std::string& instanceId); + bool handleChangePeriod(std::string& instanceId, double requestedPeriod = -1.0f); + bool handleLaunchBrowser(std::string& instanceId, std::string& url); + bool handleScroll(std::string& instanceId, bool start); + bool handleSendMessage( + std::string& instanceId, + MessageManager::ReceiverType receiver, + std::string& message); + std::string parse(std::string& uri, std::string& key); + + BoxSchemeHandler(); + ~BoxSchemeHandler(); + + // members + typedef std::map<std::string, Box*> BoxMap; + typedef std::pair<std::string, Box*> BoxMapPair; + BoxMap m_boxMap; + // members for service + std::shared_ptr<PeriodChanger> m_periodChanger; + std::shared_ptr<MessageManager> m_messageManager; + static BoxSchemeHandler* s_instance; +}; + +#endif // BOX_SCHEME_HANDLER_H + diff --git a/src_mobile/Core/BoxState.cpp b/src_mobile/Core/BoxState.cpp new file mode 100644 index 0000000..9460857 --- /dev/null +++ b/src_mobile/Core/BoxState.cpp @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file BoxState.cpp + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#include "IBoxContext.h" +#include "IBoxState.h" +#include "BoxState.h" + +// BoxState +void BoxState::switchState() +{ + // TODO this creation may be wrong.. + m_context->setState(IBoxStatePtr(this)); +} + +void BoxState::setContext(IBoxContextPtr context) +{ + m_context = context; +} + +IBoxContextPtr BoxState::getContext() +{ + return m_context; +} + +// BoxReadyState +IBoxStatePtr BoxInitState::permitShow() +{ + return IBoxStatePtr(BoxShowState::create(getContext())); +} + +// BoxShowState +IBoxStatePtr BoxShowState::permitShow() +{ + // In this case, existing state needn't to be changed + return IBoxStatePtr(this); +} + +IBoxStatePtr BoxShowState::permitHide() +{ + return IBoxStatePtr(BoxHideState::create(getContext())); +} + +IBoxStatePtr BoxShowState::permitOpenPd() +{ + return IBoxStatePtr(BoxOpenPdState::create(getContext())); +} + +IBoxStatePtr BoxShowState::permitPause() +{ + return IBoxStatePtr(BoxPauseState::create(getContext())); +} + +// BoxHideState +IBoxStatePtr BoxHideState::permitShutdown() +{ + // In this case, existing state needn't to be changed + // because there is no state to be changed from Hide State + return IBoxStatePtr(this); +} + +// BoxOpenPdState +IBoxStatePtr BoxOpenPdState::permitClosePd() +{ + return IBoxStatePtr(BoxClosePdState::create(getContext())); +} + +// BoxClosePdState +IBoxStatePtr BoxClosePdState::permitShow() +{ + return IBoxStatePtr(BoxShowState::create(getContext())); +} + +// BoxPauseState +IBoxStatePtr BoxPauseState::permitResume() +{ + return IBoxStatePtr(BoxResumeState::create(getContext())); +} + +IBoxStatePtr BoxPauseState::permitHide() +{ + return IBoxStatePtr(BoxHideState::create(getContext())); +} + +// BoxResumeState +IBoxStatePtr BoxResumeState::permitShow() +{ + return IBoxStatePtr(BoxShowState::create(getContext())); +} + +IBoxStatePtr BoxResumeState::permitHide() +{ + return IBoxStatePtr(BoxHideState::create(getContext())); +} diff --git a/src_mobile/Core/BoxState.h b/src_mobile/Core/BoxState.h new file mode 100644 index 0000000..5023386 --- /dev/null +++ b/src_mobile/Core/BoxState.h @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file BoxState.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef BOX_STATE +#define BOX_STATE + +#include "IBoxState.h" +#include "IBoxContext.h" + +/* +#define CHECK_BOX_STATE(currentState, operation) \ + IBoxStatePtr state; \ + try { \ + state = currentState->operation(); \ + } catch (...) { \ + return false; \ + } \ + +#define SWITCH_BOX_STATE() \ + state->switchState() \ +*/ + +#define CHECK_BOX_STATE(currentState, operation) +#define SWITCH_BOX_STATE() + +class BoxState: public IBoxState { + public: + virtual IBoxStatePtr permitShow() { throw this; }; + virtual IBoxStatePtr permitHide() { throw this; }; + virtual IBoxStatePtr permitResume() { throw this; }; + virtual IBoxStatePtr permitPause() { throw this; }; + virtual IBoxStatePtr permitOpenPd() { throw this; }; + virtual IBoxStatePtr permitClosePd() { throw this ; }; + virtual IBoxStatePtr permitShutdown() { throw this; }; + virtual void switchState(); + virtual ~BoxState() {}; + + protected: + explicit BoxState(IBoxContextPtr context) : m_context(context) {}; + IBoxContextPtr getContext(); + + private: + void setContext(IBoxContextPtr context); + IBoxContextPtr m_context; +}; + +class BoxInitState: public BoxState { + public: + static IBoxStatePtr create(IBoxContextPtr context) + { + return IBoxStatePtr(new BoxInitState(context)); + }; + virtual IBoxStatePtr permitShow(); + virtual ~BoxInitState() {}; + + private: + explicit BoxInitState(IBoxContextPtr context) : BoxState(context) {}; +}; + +class BoxShowState: public BoxState { + public: + static IBoxStatePtr create(IBoxContextPtr context) + { + return IBoxStatePtr(new BoxShowState(context)); + }; + virtual IBoxStatePtr permitShow(); + virtual IBoxStatePtr permitHide(); + virtual IBoxStatePtr permitOpenPd(); + virtual IBoxStatePtr permitPause(); + virtual ~BoxShowState() {}; + + private: + explicit BoxShowState(IBoxContextPtr context) : BoxState(context) {}; +}; + +class BoxHideState: public BoxState { + public: + static IBoxStatePtr create(IBoxContextPtr context) + { + return IBoxStatePtr(new BoxHideState(context)); + }; + virtual IBoxStatePtr permitShutdown(); + virtual ~BoxHideState() {}; + + private: + explicit BoxHideState(IBoxContextPtr context) : BoxState(context) {}; +}; + +class BoxOpenPdState: public BoxState { + public: + static IBoxStatePtr create(IBoxContextPtr context) + { + return IBoxStatePtr(new BoxOpenPdState(context)); + }; + virtual IBoxStatePtr permitClosePd(); + virtual ~BoxOpenPdState() {}; + + private: + explicit BoxOpenPdState(IBoxContextPtr context) : BoxState(context) {}; +}; + +class BoxClosePdState: public BoxState { + public: + static IBoxStatePtr create(IBoxContextPtr context) + { + return IBoxStatePtr(new BoxClosePdState(context)); + }; + virtual IBoxStatePtr permitShow(); + virtual ~BoxClosePdState() {}; + + private: + explicit BoxClosePdState(IBoxContextPtr context) : BoxState(context) {}; +}; + +class BoxPauseState: public BoxState { + public: + static IBoxStatePtr create(IBoxContextPtr context) + { + return IBoxStatePtr(new BoxPauseState(context)); + }; + virtual IBoxStatePtr permitResume(); + virtual IBoxStatePtr permitHide(); + virtual ~BoxPauseState() {}; + + private: + explicit BoxPauseState(IBoxContextPtr context) : BoxState(context) {}; +}; + +class BoxResumeState: public BoxState { + public: + static IBoxStatePtr create(IBoxContextPtr context) + { + return IBoxStatePtr(new BoxResumeState(context)); + }; + virtual IBoxStatePtr permitShow(); + virtual IBoxStatePtr permitHide(); + virtual ~BoxResumeState() {}; + + private: + explicit BoxResumeState(IBoxContextPtr context) : BoxState(context) {}; +}; +#endif // BOX_STATE diff --git a/src_mobile/Core/BoxUpdateTimer.cpp b/src_mobile/Core/BoxUpdateTimer.cpp new file mode 100644 index 0000000..73974e7 --- /dev/null +++ b/src_mobile/Core/BoxUpdateTimer.cpp @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file BoxUpdateTimer.cpp + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#include <Ecore.h> +#include <Core/Util/Log.h> +#include "BoxUpdateTimer.h" + +#define UPDATE_TIME_MIN 1800.0f + +BoxUpdateTimer::BoxUpdateTimer(float period, Ecore_Task_Cb callback, void* data) + : m_period(period) + , m_callback(callback) + , m_data(data) + , m_timer() +{ + LogD("enter"); +} + +BoxUpdateTimer::~BoxUpdateTimer() +{ + LogD("enter"); +} + +void BoxUpdateTimer::start() +{ + if (m_period <= 0.0f ) { + return; + } + + if (m_period < UPDATE_TIME_MIN) { + LogD("reset to minimum period(%f)", UPDATE_TIME_MIN); + m_period = UPDATE_TIME_MIN; + } + + if (m_timer) { + stop(); + } + + m_timer = ecore_timer_add(m_period, m_callback, m_data); +} + +void BoxUpdateTimer::stop() +{ + if (m_timer) { + ecore_timer_del(m_timer); + m_timer = NULL; + } +} + +void BoxUpdateTimer::resume() +{ + LogD("enter"); + ecore_timer_thaw(m_timer); +} + +void BoxUpdateTimer::pause() +{ + LogD("enter"); + ecore_timer_freeze(m_timer); +} + +void BoxUpdateTimer::restart() +{ + if (m_timer) { + ecore_timer_reset(m_timer); + } else { + start(); + } +} + +void BoxUpdateTimer::setPeriod(float period) +{ + m_period = period; + restart(); +} diff --git a/src_mobile/Core/BoxUpdateTimer.h b/src_mobile/Core/BoxUpdateTimer.h new file mode 100644 index 0000000..04bf046 --- /dev/null +++ b/src_mobile/Core/BoxUpdateTimer.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file BoxUpdateTimer.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef BOX_UPDATE_TIMER_H +#define BOX_UPDATE_TIMER_H + +#include <Ecore.h> +#include "Util/ITimer.h" + +class BoxUpdateTimer: public ITimer { + public: + static ITimerPtr create(float period, Ecore_Task_Cb callback, void* data) + { + return ITimerPtr(new BoxUpdateTimer(period, callback, data)); + }; + void start(); + void stop(); + void resume(); + void pause(); + void restart(); + void setPeriod(float period); + ~BoxUpdateTimer(); + + private: + explicit BoxUpdateTimer(float period, Ecore_Task_Cb callback, void* data); + float m_period; + Ecore_Task_Cb m_callback; + void* m_data; + Ecore_Timer* m_timer; +}; + +#endif // BOX_UPDATE_TIMER_H diff --git a/src_mobile/Core/Buffer/BoxRenderBuffer.cpp b/src_mobile/Core/Buffer/BoxRenderBuffer.cpp new file mode 100644 index 0000000..0599d99 --- /dev/null +++ b/src_mobile/Core/Buffer/BoxRenderBuffer.cpp @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file BoxRenderBuffer.cpp + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#include <string> +#include <Ecore.h> +#include <Evas.h> +#include <provider.h> +#include <provider_buffer.h> +#include <Core/Util/Log.h> +#include <Core/Util/Util.h> +#include "RenderBuffer.h" +#include "BoxRenderBuffer.h" + +BoxRenderBuffer::BoxRenderBuffer( + std::string boxId, std::string instanceId, + int width, int height) + : m_boxId(boxId) + , m_instanceId(instanceId) + , m_width(width) + , m_height(height) +{ +} + +BoxRenderBuffer::~BoxRenderBuffer() +{ +} + +BufferInfoPtr BoxRenderBuffer::acquireBuffer() +{ + LogD("enter"); + + BufferInfoPtr bufferInfo = + provider_buffer_acquire( + TYPE_LB, + m_boxId.c_str(), + m_instanceId.c_str(), + m_width, + m_height, + sizeof(int), + handleTouchEventCallback, + this); + return bufferInfo; +} + +void BoxRenderBuffer::updateBuffer() +{ + LogD("enter"); + provider_send_updated( + m_boxId.c_str(), + m_instanceId.c_str(), + m_width, m_height, + 0, NULL, NULL); +} + +int BoxRenderBuffer::handleTouchEventCallback( + BufferInfoPtr bufferInfo, + buffer_event event, + double timestamp, + double x, + double y, + void* data) +{ + LogD("enter"); + UNUSED_PARAM(bufferInfo); + + BoxRenderBuffer* This = static_cast<BoxRenderBuffer*>(data); + TouchType type; + switch (event) { + case BUFFER_EVENT_MOVE: + type = TOUCH_EVENT_MOVE; + break; + case BUFFER_EVENT_DOWN: + type = TOUCH_EVENT_DOWN; + break; + case BUFFER_EVENT_UP: + type = TOUCH_EVENT_UP; + break; + default: + type = TOUCH_EVENT_UNRECOGNIZED; + break; + } + + if (type != TOUCH_EVENT_UNRECOGNIZED) { + This->didHandleTouchEvent(type, timestamp, x, y); + } + return 0; +} + +void BoxRenderBuffer::didHandleTouchEvent( + TouchType type, double timestamp, double x, double y) +{ + // timestamp format sent by viewer is not same to the timestamp format used by webkit-efl + // so web-provider should get timestamp using ecore_time_get() + // and then feed event with the timestamp to webkit + + LogD("enter"); + switch (type) { + case TOUCH_EVENT_MOVE: + LogD("move event"); + evas_event_feed_mouse_move( + getCanvas(), x * m_width, y * m_height, ecore_time_get() * 1000, NULL); + break; + case TOUCH_EVENT_DOWN: + LogD("down event"); + evas_event_feed_mouse_move( + getCanvas(), x * m_width, y * m_height, ecore_time_get() * 1000, NULL); + evas_event_feed_mouse_down( + getCanvas(), 1, EVAS_BUTTON_NONE, 0, NULL); + break; + case TOUCH_EVENT_UP: + LogD("up event"); + evas_event_feed_mouse_up( + getCanvas(), 1, EVAS_BUTTON_NONE, 0, NULL); + break; + default: + LogD("wrong event"); + break; + } +} diff --git a/src_mobile/Core/Buffer/BoxRenderBuffer.h b/src_mobile/Core/Buffer/BoxRenderBuffer.h new file mode 100644 index 0000000..4213e72 --- /dev/null +++ b/src_mobile/Core/Buffer/BoxRenderBuffer.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file BoxRenderBuffer.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef BOX_RENDER_BUFFER_H +#define BOX_RENDER_BUFFER_H + +#include <string> +#include <provider_buffer.h> +#include "IRenderBuffer.h" +#include "RenderBuffer.h" + +#define EXPORT_CLASS __attribute__ ((visibility("default")) + +class EXPORT_CLASS BoxRenderBuffer: public RenderBuffer { + public: + enum TouchType { + TOUCH_EVENT_UNRECOGNIZED = -1, + TOUCH_EVENT_MOVE = 0, + TOUCH_EVENT_DOWN, + TOUCH_EVENT_UP + }; + + static IRenderBufferPtr create( + std::string boxId, std::string instanceId, + int width, int height) + { + return IRenderBufferPtr(new BoxRenderBuffer( + boxId, instanceId, width, height)); + + } + ~BoxRenderBuffer(); + + protected: + // this function may be overriden by derived class + virtual void didHandleTouchEvent( + TouchType type, double timestamp, double x, double y); + + BoxRenderBuffer( + std::string boxId, std::string instanceId, + int width, int height); + + private: + // RenderBuffer Implementation + int getWidth() { return m_width; }; + int getHeight() { return m_height; }; + void setWidth(int width) { m_width = width; }; + void setHeight(int height) { m_height = height; }; + BufferInfoPtr acquireBuffer(); + void updateBuffer(); + + // touch callback + static int handleTouchEventCallback( + BufferInfoPtr bufferInfo, + buffer_event event, + double timestamp, + double x, + double y, + void* data); + + // members + std::string m_boxId; + std::string m_instanceId; + int m_width; + int m_height; +}; + +#endif // BOX_RENDER_BUFFER_H diff --git a/src_mobile/Core/Buffer/CMakeLists.txt b/src_mobile/Core/Buffer/CMakeLists.txt new file mode 100644 index 0000000..e710dc3 --- /dev/null +++ b/src_mobile/Core/Buffer/CMakeLists.txt @@ -0,0 +1,67 @@ +# Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved +# +# Licensed under the Flora License, Version 1.1 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://floralicense.org/license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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) + +SET(TARGET_NAME ${TARGET_CORE_BUFFER}) +SET(DEPS ${TARGET_NAME}_DEPS) + +PKG_CHECK_MODULES(${DEPS} + ecore + ecore-evas + evas + provider + dlog + REQUIRED +) +ADD_DEFINITIONS(${${DEPS}_CFLAGS}) + +SET(SRCS + ${CMAKE_CURRENT_SOURCE_DIR}/RenderBuffer.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/RenderBufferFactory.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/BoxRenderBuffer.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/PdRenderBuffer.cpp +) + +SET(HEADERS + ${${DEPS}_INCLUDE_DIRS} + ${CMAKE_CURRENT_SOURCE_DIR} +) +INCLUDE_DIRECTORIES(${HEADERS}) + +ADD_LIBRARY(${TARGET_NAME} STATIC ${SRCS}) + +SET_TARGET_PROPERTIES(${TARGET_NAME} PROPERTIES + COMPILE_FLAGS -fPIC + LINK_FLAGS "-Wl,--as-needed -Wl,--hash-style=both" +) + +SET_TARGET_PROPERTIES(${TARGET_NAME} + PROPERTIES + SOVERSION ${CMAKE_PROJECT_API_VERSION} + VERSION ${CMAKE_PROJECT_VERSION} +) + +TARGET_LINK_LIBRARIES(${TARGET_NAME} + ${${DEPS}_LIBRARIES} +) + +GET_FILENAME_COMPONENT(CURRENT_DIR_NAME ${CMAKE_CURRENT_SOURCE_DIR} NAME) +GET_FILENAME_COMPONENT(PARENT_DIR_ABSOLUTE_PATH ${CMAKE_CURRENT_SOURCE_DIR} PATH) +GET_FILENAME_COMPONENT(PARENT_DIR_NAME ${PARENT_DIR_ABSOLUTE_PATH} NAME) + +INSTALL_FILE(IRenderBuffer.h include/${PROJECT_NAME}/${PARENT_DIR_NAME}/${CURRENT_DIR_NAME}) +INSTALL_FILE(RenderBuffer.h include/${PROJECT_NAME}/${PARENT_DIR_NAME}/${CURRENT_DIR_NAME}) +INSTALL_FILE(RenderBufferFactory.h include/${PROJECT_NAME}/${PARENT_DIR_NAME}/${CURRENT_DIR_NAME}) +INSTALL_FILE(BoxRenderBuffer.h include/${PROJECT_NAME}/${PARENT_DIR_NAME}/${CURRENT_DIR_NAME}) diff --git a/src_mobile/Core/Buffer/IRenderBuffer.h b/src_mobile/Core/Buffer/IRenderBuffer.h new file mode 100644 index 0000000..0c05e86 --- /dev/null +++ b/src_mobile/Core/Buffer/IRenderBuffer.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file IRenderBuffer.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef I_RENDER_BUFFER_H +#define I_RENDER_BUFFER_H + +#include <memory> +#include <Evas.h> +#include <Util/Noncopyable.h> + +class IRenderBuffer: Noncopyable { + public: + virtual bool allocate() = 0; + virtual bool reallocate(int width, int height) = 0; + virtual bool free() = 0; + virtual void startCanvasUpdate() = 0; + virtual void stopCanvasUpdate() = 0; + virtual Evas_Object* getWindow() = 0; + + virtual ~IRenderBuffer() {}; +}; + +typedef std::shared_ptr<IRenderBuffer> IRenderBufferPtr; + +#endif diff --git a/src_mobile/Core/Buffer/PdRenderBuffer.cpp b/src_mobile/Core/Buffer/PdRenderBuffer.cpp new file mode 100644 index 0000000..af65e08 --- /dev/null +++ b/src_mobile/Core/Buffer/PdRenderBuffer.cpp @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file PdRenderBuffer.cpp + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#include <string> +#include <Ecore.h> +#include <Evas.h> +#include <provider.h> +#include <provider_buffer.h> +#include <Core/Util/Log.h> +#include <Core/Util/Util.h> +#include "RenderBuffer.h" +#include "PdRenderBuffer.h" + +PdRenderBuffer::PdRenderBuffer( + std::string boxId, std::string instanceId, + int width, int height) + : m_boxId(boxId) + , m_instanceId(instanceId) + , m_width(width) + , m_height(height) +{ +} + +PdRenderBuffer::~PdRenderBuffer() +{ +} + +BufferInfoPtr PdRenderBuffer::acquireBuffer() +{ + BufferInfoPtr bufferInfo = + provider_buffer_acquire( + TYPE_PD, + m_boxId.c_str(), + m_instanceId.c_str(), + m_width, + m_height, + sizeof(int), + handleTouchEventCallback, + this); + + return bufferInfo; +} + +void PdRenderBuffer::updateBuffer() +{ + LogD("enter"); + provider_send_desc_updated( + m_boxId.c_str(), + m_instanceId.c_str(), + NULL); +} + +int PdRenderBuffer::handleTouchEventCallback( + BufferInfoPtr bufferInfo, + buffer_event event, + double timestamp, + double x, + double y, + void* data) +{ + LogD("enter"); + UNUSED_PARAM(bufferInfo); + + PdRenderBuffer* This = static_cast<PdRenderBuffer*>(data); + TouchType type; + switch (event) { + case BUFFER_EVENT_MOVE: + type = TOUCH_EVENT_MOVE; + break; + case BUFFER_EVENT_DOWN: + type = TOUCH_EVENT_DOWN; + break; + case BUFFER_EVENT_UP: + type = TOUCH_EVENT_UP; + break; + default: + type = TOUCH_EVENT_UNRECOGNIZED; + break; + } + + if (type != TOUCH_EVENT_UNRECOGNIZED) { + This->didHandleTouchEvent(type, timestamp, x, y); + } + return 0; +} + +void PdRenderBuffer::didHandleTouchEvent( + TouchType type, double timestamp, double x, double y) +{ + // timestamp format sent by viewer is not same to the timestamp format used by webkit-efl + // so web-provider should get timestamp using ecore_time_get() + // and then feed event with the timestamp to webkit + + switch (type) { + case TOUCH_EVENT_MOVE: + LogD("move event"); + evas_event_feed_mouse_move( + getCanvas(), x * m_width, y * m_height, ecore_time_get() * 1000, NULL); + break; + case TOUCH_EVENT_DOWN: + LogD("down event"); + evas_event_feed_mouse_move( + getCanvas(), x * m_width, y * m_height, ecore_time_get() * 1000, NULL); + evas_event_feed_mouse_down( + getCanvas(), 1, EVAS_BUTTON_NONE, 0, NULL); + break; + case TOUCH_EVENT_UP: + LogD("up event"); + evas_event_feed_mouse_up( + getCanvas(), 1, EVAS_BUTTON_NONE, 0, NULL); + break; + default: + LogD("wrong event"); + break; + } +} diff --git a/src_mobile/Core/Buffer/PdRenderBuffer.h b/src_mobile/Core/Buffer/PdRenderBuffer.h new file mode 100644 index 0000000..b2fd890 --- /dev/null +++ b/src_mobile/Core/Buffer/PdRenderBuffer.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file PdRenderBuffer.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef PD_RENDER_BUFFER_H +#define PD_RENDER_BUFFER_H + +#include <string> +#include <provider_buffer.h> +#include "IRenderBuffer.h" +#include "RenderBuffer.h" + +#define EXPORT_CLASS __attribute__ ((visibility("default")) + +class EXPORT_CLASS PdRenderBuffer: public RenderBuffer { + public: + enum TouchType { + TOUCH_EVENT_UNRECOGNIZED = -1, + TOUCH_EVENT_MOVE = 0, + TOUCH_EVENT_DOWN, + TOUCH_EVENT_UP + }; + + static IRenderBufferPtr create( + std::string boxId, std::string instanceId, + int width, int height) + { + return IRenderBufferPtr(new PdRenderBuffer(boxId, instanceId, width, height)); + } + ~PdRenderBuffer(); + + private: + void didHandleTouchEvent( + TouchType type, double timestamp, double x, double y); + + // RenderBuffer Implementation + int getWidth() { return m_width; }; + int getHeight() { return m_height; }; + void setWidth(int width) { m_width = width; }; + void setHeight(int height) { m_height = height; }; + BufferInfoPtr acquireBuffer(); + void updateBuffer(); + + // touch callback + static int handleTouchEventCallback( + BufferInfoPtr bufferInfo, + buffer_event event, + double timestamp, + double x, + double y, + void* data); + + PdRenderBuffer( + std::string boxId, std::string instanceId, + int width, int height); + + // members + std::string m_boxId; + std::string m_instanceId; + int m_width; + int m_height; +}; + +#endif // PD_RENDER_BUFFER_H diff --git a/src_mobile/Core/Buffer/RenderBuffer.cpp b/src_mobile/Core/Buffer/RenderBuffer.cpp new file mode 100755 index 0000000..1bd70b6 --- /dev/null +++ b/src_mobile/Core/Buffer/RenderBuffer.cpp @@ -0,0 +1,326 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file RenderBuffer.cpp + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#include <string> +#include <Evas.h> +#include <Ecore.h> +#include <Ecore_Evas.h> +#include <provider.h> +#include <provider_buffer.h> +#include <Core/Util/Log.h> +#include <Core/Util/Util.h> +#include "IRenderBuffer.h" +#include "RenderBuffer.h" + +RenderBuffer::RenderBuffer() + : m_bufferAddr(NULL) + , m_bufferInfo(NULL) +{ + LogD("enter"); +} + +RenderBuffer::~RenderBuffer() +{ + LogD("enter"); +} + +bool RenderBuffer::allocate() +{ + LogD("enter"); + if (m_bufferAddr) { + free(); + m_bufferAddr = NULL; + } + + Ecore_Evas* ee = + ecore_evas_buffer_allocfunc_new( + getWidth(), getHeight(), + allocateCallback, freeCallback, + this); + LogD("Using %s engine!", ecore_evas_engine_name_get(ee)); + + if (!ee) { + LogD("invalid ecore evas object"); + return false; + } + + LogD("evas ecore setting"); + + // alpha_set function access the canvas buffer directly, + // without pre/post render callback. + provider_buffer_pre_render(m_bufferInfo); + ecore_evas_alpha_set(ee, EINA_TRUE); + provider_buffer_post_render(m_bufferInfo); + ecore_evas_manual_render_set(ee, EINA_FALSE); + + // resize function will invoke the freeCallback and allocateCallback again. (internally) + ecore_evas_resize(ee, getWidth(), getHeight()); + ecore_evas_show(ee); + ecore_evas_activate(ee); + + LogD("Using %s engine!", ecore_evas_engine_name_get(ee)); + + Evas* e = ecore_evas_get(ee); + evas_image_cache_flush(e); + Evas_Object *eo = evas_object_rectangle_add(e); + evas_object_size_hint_weight_set(eo, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_color_set(eo, 0, 0, 0, 1); + evas_object_resize(eo, getWidth(), getHeight()); + + m_canvas = e; + m_win = eo; + + startCanvasUpdate(); + return true; +} + +bool RenderBuffer::reallocate(int width, int height) +{ + LogD("enter"); + stopCanvasUpdate(); + + // TODO This function should be implemented due to box resize operation + setWidth(width); + setHeight(height); + + Ecore_Evas* ee = ecore_evas_ecore_evas_get(m_canvas); + // resize function will invoke the freeCallback and allocateCallback again. (internally) + ecore_evas_resize(ee, getWidth(), getHeight()); + evas_object_resize(m_win, getWidth(), getHeight()); + startCanvasUpdate(); + return true; +} + +bool RenderBuffer::free() +{ + if (!m_canvas) { + return false; + } + + stopCanvasUpdate(); + ecore_evas_free(ecore_evas_ecore_evas_get(m_canvas)); + m_canvas = NULL; + m_win = NULL; + + return true; +} + +void RenderBuffer::startCanvasUpdate() +{ + LogD("enter"); + evas_event_callback_del( + m_canvas, + EVAS_CALLBACK_RENDER_PRE, + preRenderCallback); + + evas_event_callback_del( + m_canvas, + EVAS_CALLBACK_RENDER_POST, + postRenderCallback); + + evas_event_callback_add( + m_canvas, + EVAS_CALLBACK_RENDER_PRE, + preRenderCallback, this); + + evas_event_callback_add( + m_canvas, + EVAS_CALLBACK_RENDER_POST, + postRenderCallback, this); + +} + +void RenderBuffer::stopCanvasUpdate() +{ + LogD("enter"); + evas_event_callback_del( + m_canvas, + EVAS_CALLBACK_RENDER_PRE, + preRenderCallback); + + evas_event_callback_del( + m_canvas, + EVAS_CALLBACK_RENDER_POST, + postRenderCallback); +} + +Evas_Object* RenderBuffer::getWindow() +{ + return m_win; +} + +void RenderBuffer::preRenderCallback(void* data, Evas* canvas, void *eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(eventInfo); + + RenderBuffer *buffer = static_cast<RenderBuffer*>(data); + if (!provider_buffer_pixmap_is_support_hw(buffer->m_bufferInfo)) { + LogD("not hw backend"); + return; + } + + provider_buffer_pre_render(buffer->m_bufferInfo); + evas_damage_rectangle_add(canvas, 0, 0, buffer->getWidth(), buffer->getHeight()); +} + +void RenderBuffer::postRenderCallback(void* data, Evas* canvas, void* eventInfo) +{ + LogD("enter"); + + UNUSED_PARAM(canvas); + UNUSED_PARAM(eventInfo); + + RenderBuffer* buffer = static_cast<RenderBuffer*>(data); + + evas_data_argb_unpremul(static_cast<unsigned int*>(buffer->m_bufferAddr), buffer->getWidth() * buffer->getHeight()); +#ifdef RENDER_BUFFER_VERIFY_SHOT + { + FILE *fp; + static int idx = 0; + char filename[256]; + snprintf(filename, sizeof(filename) - 1, "/tmp/render%d-%dx%d.raw", idx++, buffer->getWidth(), buffer->getHeight()); + fp = fopen(filename, "w+"); + if (fp) { + LogD("RenderShot: %s(%d)\n", filename, buffer->getWidth() * buffer->getHeight() * sizeof(int)); + fwrite(buffer->m_bufferAddr, buffer->getWidth() * buffer->getHeight() * sizeof(int), 1, fp); + fclose(fp); + } else { + LogD("Failed to open a file: %s", filename); + } + } +#endif + LogD("/tmp/render-%dx%d.raw", buffer->getWidth(), buffer->getHeight()); + + if (!provider_buffer_pixmap_is_support_hw(buffer->m_bufferInfo)) { + provider_buffer_sync(buffer->m_bufferInfo); + buffer->updateBuffer(); + } else { + provider_buffer_post_render(buffer->m_bufferInfo); + buffer->updateBuffer(); + } +} + +void RenderBuffer::paintColor(unsigned int color) +{ + LogD("enter"); + + if (!provider_buffer_pixmap_is_support_hw(m_bufferInfo)) { + memset(m_bufferAddr, color, getWidth() * getHeight() * 4); + provider_buffer_sync(m_bufferInfo); + updateBuffer(); + } else { + preRenderCallback(this, m_canvas, NULL); + memset(m_bufferAddr, color, getWidth() * getHeight() * 4); + postRenderCallback(this, m_canvas, NULL); + } +} + +Evas* RenderBuffer::getCanvas() +{ + return m_canvas; +} + +void* RenderBuffer::allocateCallback(void* data, int size) +{ + LogD("enter"); + UNUSED_PARAM(size); + + RenderBuffer* buffer = static_cast<RenderBuffer*>(data); + + if (buffer->m_bufferInfo) { + freeCallback(data, NULL); + } + + buffer->m_bufferInfo = buffer->acquireBuffer(); + if (!buffer->m_bufferInfo) { + return NULL; + } + + // set buffer address + if (!provider_buffer_pixmap_is_support_hw(buffer->m_bufferInfo)) { + LogD("s/w evas backend"); + buffer->m_bufferAddr = provider_buffer_ref(buffer->m_bufferInfo); + } else { + LogD("h/w evas backend"); + int ret = provider_buffer_pixmap_create_hw(buffer->m_bufferInfo); + if (ret < 0) { + LogD("can't create hw pixmap"); + } + buffer->m_bufferAddr = provider_buffer_pixmap_hw_addr(buffer->m_bufferInfo); + } + + LogD("success to allocate buffer"); + return buffer->m_bufferAddr; +} + +void RenderBuffer::freeCallback(void* data, void *pix) +{ + LogD("enter"); + UNUSED_PARAM(pix); + + RenderBuffer* buffer = static_cast<RenderBuffer*>(data); + + // destroy buffer + if (!provider_buffer_pixmap_is_support_hw(buffer->m_bufferInfo)) { + provider_buffer_unref(buffer->m_bufferAddr); + } else { + provider_buffer_pixmap_destroy_hw(buffer->m_bufferInfo); + } + + provider_buffer_release(buffer->m_bufferInfo); + + buffer->m_bufferInfo = NULL; + buffer->m_bufferAddr = NULL; + + LogD("success to free buffer"); + return; +} + +Evas_Object *RenderBuffer::getSnapshot(void) +{ + LogD("enter"); + Evas_Object *snapshot; + void *tmpBuffer; + + snapshot = evas_object_image_add(m_canvas); + if (!snapshot) + return NULL; + evas_object_image_data_set(snapshot, NULL); + evas_object_image_colorspace_set(snapshot, EVAS_COLORSPACE_ARGB8888); + evas_object_image_alpha_set(snapshot, EINA_TRUE); + evas_object_image_size_set(snapshot, getWidth(), getHeight()); + + tmpBuffer = malloc(getWidth() * getHeight() * sizeof(int)); + if (tmpBuffer) { + memcpy(tmpBuffer, m_bufferAddr, getWidth() * getHeight() * sizeof(int)); + evas_data_argb_premul( + static_cast<unsigned int*>(tmpBuffer), + getWidth() * getHeight()); + evas_object_image_data_set(snapshot, tmpBuffer); + } else { + LogD("Failed to allocate heap"); + } + + evas_object_image_data_update_add(snapshot, 0, 0, getWidth(), getHeight()); + evas_object_image_fill_set(snapshot, 0, 0, getWidth(), getHeight()); + evas_object_resize(snapshot, getWidth(), getHeight()); + + return snapshot; +} diff --git a/src_mobile/Core/Buffer/RenderBuffer.h b/src_mobile/Core/Buffer/RenderBuffer.h new file mode 100644 index 0000000..b275e70 --- /dev/null +++ b/src_mobile/Core/Buffer/RenderBuffer.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file RenderBuffer.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef RENDER_BUFFER_H +#define RENDER_BUFFER_H + +#include <memory> +#include <Evas.h> +#include "IRenderBuffer.h" + +// forward declaration +struct livebox_buffer; + +// type definition +typedef struct livebox_buffer* BufferInfoPtr; +typedef void* BufferAddrPtr; + +#define EXPORT_CLASS __attribute__ ((visibility("default")) + +class EXPORT_CLASS RenderBuffer: public IRenderBuffer { + public: + // IRenderBuffer Implementation + bool allocate(); + bool reallocate(int width, int height); + bool free(); + Evas_Object* getWindow(); + void startCanvasUpdate(); + void stopCanvasUpdate(); + + static void preRenderCallback(void* data, Evas* canvas, void* eventInfo); + static void postRenderCallback(void* data, Evas* canvas, void* eventInfo); + + virtual ~RenderBuffer(); + + protected: + void paintColor(unsigned int color); + Evas* getCanvas(); + Evas_Object* getSnapshot(); + + // provided by derived class + virtual int getWidth() = 0; + virtual int getHeight() = 0; + virtual void setWidth(int width) = 0; + virtual void setHeight(int height) = 0; + virtual BufferInfoPtr acquireBuffer() = 0; + virtual void updateBuffer() = 0; + + RenderBuffer(); + + private: + // callbacks + static void* allocateCallback(void* data, int size); + static void freeCallback(void* data, void *pix); + + // members + Evas* m_canvas; + Evas_Object* m_win; + BufferAddrPtr m_bufferAddr; + BufferInfoPtr m_bufferInfo; +}; + +#endif diff --git a/src_mobile/Core/Buffer/RenderBufferFactory.cpp b/src_mobile/Core/Buffer/RenderBufferFactory.cpp new file mode 100644 index 0000000..5d6a55f --- /dev/null +++ b/src_mobile/Core/Buffer/RenderBufferFactory.cpp @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file RenderBufferFactory.cpp + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#include <string> +#include <Core/Util/Log.h> +#include "IRenderBuffer.h" +#include "BoxRenderBuffer.h" +#include "PdRenderBuffer.h" +#include "RenderBufferFactory.h" + +IRenderBufferPtr RenderBufferFactory::create( + RenderBufferType type, + std::string boxId, + std::string instanceId, + int width, + int height) +{ + LogD("enter"); + IRenderBufferPtr buffer; + switch (type) { + case RENDER_BUFFER_TYPE_BOX: + buffer = BoxRenderBuffer::create(boxId, instanceId, width, height); + break; + case RENDER_BUFFER_TYPE_PD: + buffer = PdRenderBuffer::create(boxId, instanceId, width, height); + break; + default: + LogD("not available type"); + break; + } + + return buffer; +} diff --git a/src_mobile/Core/Buffer/RenderBufferFactory.h b/src_mobile/Core/Buffer/RenderBufferFactory.h new file mode 100644 index 0000000..9eff1e3 --- /dev/null +++ b/src_mobile/Core/Buffer/RenderBufferFactory.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file RenderBufferFactory.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef RENDER_BUFFER_FACTORY_H +#define RENDER_BUFFER_FACTORY_H + +#include "IRenderBuffer.h" + +#ifndef EXPORT_API +#define EXPORT_API __attribute__ ((visibility("default"))) +#endif + +namespace RenderBufferFactory { + +enum RenderBufferType : int +{ + RENDER_BUFFER_TYPE_BOX = 0, + RENDER_BUFFER_TYPE_PD, +}; + +EXPORT_API IRenderBufferPtr create( + RenderBufferType type, + std::string boxId, + std::string instanceId, + int width, + int height); +} + +#endif // RENDER_BUFFER_FACTORY_H diff --git a/src_mobile/Core/CMakeLists.txt b/src_mobile/Core/CMakeLists.txt new file mode 100644 index 0000000..5c4c0e5 --- /dev/null +++ b/src_mobile/Core/CMakeLists.txt @@ -0,0 +1,86 @@ +# Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved +# +# Licensed under the Flora License, Version 1.1 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://floralicense.org/license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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) + +SET(TARGET_NAME ${TARGET_CORE}) +SET(TARGET_CORE_BUFFER web-provider-core-buffer) +SET(TARGET_CORE_VIEW web-provider-core-view) +SET(TARGET_CORE_SERVICE web-provider-core-service) +SET(TARGET_CORE_UTIL web-provider-core-util) +SET(DEPS ${TARGET_NAME}_DEPS) + +PKG_CHECK_MODULES(${DEPS} + ecore + ewebkit2 + dlog + REQUIRED +) +ADD_DEFINITIONS(${${DEPS}_CFLAGS}) + +SET(SRCS + ${CMAKE_CURRENT_SOURCE_DIR}/Box.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/BoxManager.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/BoxState.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/BoxUpdateTimer.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/BoxSchemeHandler.cpp +) + +SET(HEADERS + ${${DEPS}_INCLUDE_DIRS} + ${CMAKE_CURRENT_SOURCE_DIR} +) +INCLUDE_DIRECTORIES(${HEADERS}) + +ADD_LIBRARY(${TARGET_NAME} SHARED ${SRCS}) + +SET_TARGET_PROPERTIES(${TARGET_NAME} PROPERTIES + COMPILE_FLAGS -fPIC + LINK_FLAGS "-Wl,--as-needed -Wl,--hash-style=both" +) + +SET_TARGET_PROPERTIES(${TARGET_NAME} + PROPERTIES + SOVERSION ${CMAKE_PROJECT_API_VERSION} + VERSION ${CMAKE_PROJECT_VERSION} +) + +TARGET_LINK_LIBRARIES(${TARGET_NAME} + ${${DEPS}_LIBRARIES} + "-Wl,--whole-archive" + ${TARGET_CORE_VIEW} + ${TARGET_CORE_BUFFER} + ${TARGET_CORE_SERVICE} + ${TARGET_CORE_UTIL} + "-Wl,--no-whole-archive" +) + +ADD_SUBDIRECTORY(Buffer) +ADD_SUBDIRECTORY(View) +ADD_SUBDIRECTORY(Service) +ADD_SUBDIRECTORY(Util) + +INSTALL(TARGETS ${TARGET_NAME} + DESTINATION lib + PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE + GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE +) + +GET_FILENAME_COMPONENT(CURRENT_DIR_NAME ${CMAKE_CURRENT_SOURCE_DIR} NAME) + +INSTALL_FILE(IBox.h include/${PROJECT_NAME}/${CURRENT_DIR_NAME}) +INSTALL_FILE(BoxData.h include/${PROJECT_NAME}/${CURRENT_DIR_NAME}) +INSTALL_FILE(IBoxManager.h include/${PROJECT_NAME}/${CURRENT_DIR_NAME}) +INSTALL_FILE(BoxManager.h include/${PROJECT_NAME}/${CURRENT_DIR_NAME}) +INSTALL_FILE(BoxSchemeHandler.h include/${PROJECT_NAME}/${CURRENT_DIR_NAME}) diff --git a/src_mobile/Core/IBox.h b/src_mobile/Core/IBox.h new file mode 100644 index 0000000..bea5570 --- /dev/null +++ b/src_mobile/Core/IBox.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file IBox.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef I_BOX_H +#define I_BOX_H + +#include <string> +#include <memory> +#include <ctime> +#include <ewk_view.h> +#include <ewk_context.h> + +class IBox { + public: + // functions for lifecycle + virtual bool show() = 0; + virtual bool hide() = 0; + virtual bool resize(int width, int height) = 0; + virtual bool resume() = 0; + virtual bool pause(bool background) = 0; + virtual bool openPd(int width, int height, double x, double y) = 0; + virtual bool closePd() = 0; + virtual bool update(time_t requestTime, std::string& contentInfo) = 0; + + // functions for getting/setting box's data by BoxManager + virtual bool changePeriod(float period) = 0; + virtual bool isCurrentTab() = 0; + virtual time_t getLastUpdateRequestTime() = 0; + virtual BoxInfoPtr getBoxInfo() = 0; + + //virtual IBox& operator=(const IBox& rhs) = 0; + //virtual bool operator==(const IBox& rhs) const = 0; + //virtual bool operator!=(const IBox& rhs) const = 0; + virtual ~IBox() {}; +}; + +typedef std::shared_ptr<IBox> IBoxPtr; +typedef std::shared_ptr<Ewk_Context> EwkContextPtr; + +#endif //I_BOX_H diff --git a/src_mobile/Core/IBoxContext.h b/src_mobile/Core/IBoxContext.h new file mode 100644 index 0000000..8dfa2a7 --- /dev/null +++ b/src_mobile/Core/IBoxContext.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file IBoxContext.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef I_BOX_CONTEXT +#define I_BOX_CONTEXT + +#include "IBoxState.h" + +class IBoxContext { + public: + virtual void setState(IBoxStatePtr state) = 0; + virtual ~IBoxContext() {}; +}; + +typedef std::shared_ptr<IBoxContext> IBoxContextPtr; + +#endif // I_BOX_CONTEXT diff --git a/src_mobile/Core/IBoxManager.h b/src_mobile/Core/IBoxManager.h new file mode 100644 index 0000000..d441ed1 --- /dev/null +++ b/src_mobile/Core/IBoxManager.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file IBoxManager.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef I_BOX_MANAGER_H +#define I_BOX_MANAGER_H + +#include <string> +#include <Util/Noncopyable.h> +#include <Plugin/box_plugin_interface.h> +#include "BoxData.h" + +class IBoxManager: Noncopyable { + public: + virtual bool doCommand(const request_cmd_type, const BoxInfoPtr&) = 0; + virtual ~IBoxManager() {}; +}; + +typedef std::shared_ptr<IBoxManager> IBoxManagerPtr; + +#endif // I_BOX_MANAGER_H diff --git a/src_mobile/Core/IBoxState.h b/src_mobile/Core/IBoxState.h new file mode 100644 index 0000000..d798dc1 --- /dev/null +++ b/src_mobile/Core/IBoxState.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file IBoxState.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef I_BOX_STATE +#define I_BOX_STATE + +#include <memory> + +class IBoxState; +typedef std::shared_ptr<IBoxState> IBoxStatePtr; + +class IBoxState { + public: + virtual IBoxStatePtr permitShow() = 0; + virtual IBoxStatePtr permitHide() = 0; + virtual IBoxStatePtr permitResume() = 0; + virtual IBoxStatePtr permitPause() = 0; + virtual IBoxStatePtr permitOpenPd() = 0; + virtual IBoxStatePtr permitClosePd() = 0; + virtual IBoxStatePtr permitShutdown() = 0; + virtual void switchState() = 0; + virtual ~IBoxState() {}; +}; + +#endif // I_BOX_STATE diff --git a/src_mobile/Core/Service/AppControl.cpp b/src_mobile/Core/Service/AppControl.cpp new file mode 100644 index 0000000..761dd93 --- /dev/null +++ b/src_mobile/Core/Service/AppControl.cpp @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file LaunchBrowser.cpp + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ + +#include <string> +#include <app_service.h> +#include <Core/Util/Log.h> +#include "AppControl.h" + +namespace Service { +namespace AppControl { + +bool launchBrowser(std::string& url) +{ + LogD("enter"); + + service_h handle = NULL; + int ret = SERVICE_ERROR_NONE; + + ret = service_create(&handle); + if (ret != SERVICE_ERROR_NONE) { + LogD("failed to create service"); + return false; + } + + ret = service_set_operation(handle, SERVICE_OPERATION_VIEW); + if (ret != SERVICE_ERROR_NONE) { + LogD("failed to set operation"); + service_destroy(handle); + return false; + } + + ret = service_set_uri(handle, url.c_str()); + if (ret != SERVICE_ERROR_NONE) { + LogD("failed to set url"); + service_destroy(handle); + return false; + } + + ret = service_send_launch_request(handle, NULL, NULL); + if (ret != SERVICE_ERROR_NONE) { + LogD("failed to request launch"); + service_destroy(handle); + return false; + } + + LogD("success to launch browser: %s", url.c_str()); + service_destroy(handle); + + return true; +} + +bool launchDownloader(std::string& url, std::string& cookie) +{ + LogD("enter"); + + service_h handle = NULL; + int ret = SERVICE_ERROR_NONE; + + if (url.empty()) { + LogD("invalid arguments"); + return false; + } + + ret = service_create(&handle); + if (ret != SERVICE_ERROR_NONE) { + LogD("failed to create service"); + return false; + } + + ret = service_set_operation(handle, SERVICE_OPERATION_DOWNLOAD); + if (ret != SERVICE_ERROR_NONE) { + LogD("failed to set operation"); + service_destroy(handle); + return false; + } + + ret = service_set_uri(handle, url.c_str()); + if (ret != SERVICE_ERROR_NONE) { + LogD("failed to set url"); + service_destroy(handle); + return false; + } + + if (!cookie.empty()) { + ret = service_add_extra_data(handle, "cookie", cookie.c_str()); + if (ret != SERVICE_ERROR_NONE) { + LogD("failed to set cookie"); + service_destroy(handle); + return false; + } + } + + ret = service_send_launch_request(handle, NULL, NULL); + if (ret != SERVICE_ERROR_NONE) { + LogD("failed to request launch"); + service_destroy(handle); + return false; + } + + LogD("success to launch downloader"); + service_destroy(handle); + + return true; +} + +} // AppControl +} // Service diff --git a/src_mobile/Core/Service/AppControl.h b/src_mobile/Core/Service/AppControl.h new file mode 100644 index 0000000..5693873 --- /dev/null +++ b/src_mobile/Core/Service/AppControl.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file AppControl.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ + +#include <string> + +namespace Service { +namespace AppControl { + +bool launchBrowser(std::string& url); +bool launchDownloader(std::string& url, std::string& cookie); + +} +} // Service diff --git a/src_mobile/Core/Service/CMakeLists.txt b/src_mobile/Core/Service/CMakeLists.txt new file mode 100755 index 0000000..ad8fa36 --- /dev/null +++ b/src_mobile/Core/Service/CMakeLists.txt @@ -0,0 +1,72 @@ +# Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved +# +# Licensed under the Flora License, Version 1.1 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://floralicense.org/license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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) + +SET(TARGET_NAME ${TARGET_CORE_SERVICE}) +SET(DEPS ${TARGET_NAME}_DEPS) + +PKG_CHECK_MODULES(${DEPS} + dlog + capi-appfw-application + livebox-service + evas + eina + ecore-x + elementary + efl-assist + provider + ecore + REQUIRED +) +ADD_DEFINITIONS(${${DEPS}_CFLAGS}) + +SET(SRCS + ${CMAKE_CURRENT_SOURCE_DIR}/AppControl.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/PeriodChanger.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/ScrollHolder.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/MessageManager.cpp +) + +SET(HEADERS + ${${DEPS}_INCLUDE_DIRS} + ${CMAKE_CURRENT_SOURCE_DIR} +) +INCLUDE_DIRECTORIES(${HEADERS}) + +ADD_LIBRARY(${TARGET_NAME} STATIC ${SRCS}) + +SET_TARGET_PROPERTIES(${TARGET_NAME} PROPERTIES + COMPILE_FLAGS -fPIC + LINK_FLAGS "-Wl,--as-needed -Wl,--hash-style=both" +) + +SET_TARGET_PROPERTIES(${TARGET_NAME} + PROPERTIES + SOVERSION ${CMAKE_PROJECT_API_VERSION} + VERSION ${CMAKE_PROJECT_VERSION} +) + +TARGET_LINK_LIBRARIES(${TARGET_NAME} + ${${DEPS}_LIBRARIES} +) + +GET_FILENAME_COMPONENT(CURRENT_DIR_NAME ${CMAKE_CURRENT_SOURCE_DIR} NAME) +GET_FILENAME_COMPONENT(PARENT_DIR_ABSOLUTE_PATH ${CMAKE_CURRENT_SOURCE_DIR} PATH) +GET_FILENAME_COMPONENT(PARENT_DIR_NAME ${PARENT_DIR_ABSOLUTE_PATH} NAME) + +INSTALL_FILE(PeriodChanger.h include/${PROJECT_NAME}/${PARENT_DIR_NAME}/${CURRENT_DIR_NAME}) +INSTALL_FILE(MessageManager.h include/${PROJECT_NAME}/${PARENT_DIR_NAME}/${CURRENT_DIR_NAME}) +INSTALL_FILE(ScrollHolder.h include/${PROJECT_NAME}/${PARENT_DIR_NAME}/${CURRENT_DIR_NAME}) +INSTALL_FILE(AppControl.h include/${PROJECT_NAME}/${PARENT_DIR_NAME}/${CURRENT_DIR_NAME}) diff --git a/src_mobile/Core/Service/MessageManager.cpp b/src_mobile/Core/Service/MessageManager.cpp new file mode 100755 index 0000000..3199d86 --- /dev/null +++ b/src_mobile/Core/Service/MessageManager.cpp @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file MessageMenager.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ + +#include <string> +#include <Evas.h> +#include <Eina.h> +#include <ewk_view.h> +#include <Core/Util/Log.h> +#include <Core/Util/Util.h> +#include "MessageManager.h" + +namespace Service { + +static const std::string jsFireWindowEventFunction("webprovider.fireAppWidgetEvent"); +static const std::string jsPdMessageEvent("pdmessage"); +static const std::string jsBoxMessageEvent("boxmessage"); + +MessageManager::MessageManager() +{ + LogD("enter"); +} + +MessageManager::~MessageManager() +{ + LogD("enter"); +} + +bool MessageManager::send(Evas_Object* webview, ReceiverType receiver, std::string& message) +{ + LogD("enter"); + + std::string eventName; + if(!webview) { + return false; + } + // set message event name triggered by receiver + switch (receiver) { + case TO_BOX: + eventName = jsPdMessageEvent; + break; + case TO_PD: + eventName = jsBoxMessageEvent; + break; + default: + return false; + } + + std::string script = jsFireWindowEventFunction; + script += "(\""; + script += eventName; + script += "\", \""; + script += message; + script +="\");"; + LogD("calling javascript: %s", script.c_str()); + + // execute js code for sending message + if (EINA_FALSE == ewk_view_script_execute( + webview, script.c_str(), executeScriptCallback, this)) { + LogD("ewk_view_script_execute fail."); + } + + return true; +} + +void MessageManager::executeScriptCallback( + Evas_Object* webview, const char* result, void* data) +{ + LogD("enter"); + UNUSED_PARAM(webview); + UNUSED_PARAM(data); + + std::string resultStr(result ? result : "null"); + LogD("result: %s", resultStr.c_str()); +} +} // Service diff --git a/src_mobile/Core/Service/MessageManager.h b/src_mobile/Core/Service/MessageManager.h new file mode 100644 index 0000000..d19b69d --- /dev/null +++ b/src_mobile/Core/Service/MessageManager.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file MessageManager.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ + +#ifndef MESSAGE_MANAGER_H +#define MESSAGE_MANAGER_H + +#include <string> +#include <memory> +#include <Evas.h> + +namespace Service { + +class MessageManager; +typedef std::shared_ptr<MessageManager> MessageManagerPtr; + +class MessageManager { + public: + enum ReceiverType { + TO_BOX, + TO_PD + }; + + static MessageManagerPtr create() { + return MessageManagerPtr(new MessageManager()); + } + bool send(Evas_Object* webview, ReceiverType receiver, std::string& message); + ~MessageManager(); + + private: + static void executeScriptCallback( + Evas_Object* webview, const char* result, void* data); + MessageManager(); +}; +} // Service + +#endif // MESSAGE_MANAGER_H diff --git a/src_mobile/Core/Service/PeriodChanger.cpp b/src_mobile/Core/Service/PeriodChanger.cpp new file mode 100755 index 0000000..91a000a --- /dev/null +++ b/src_mobile/Core/Service/PeriodChanger.cpp @@ -0,0 +1,287 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file PeriodChanger.cpp + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ + +#include <string> +#include <Evas.h> +#include <Ecore_X.h> +#include <Ecore.h> +#include <Elementary.h> +#include <efl_assist.h> +#include <livebox-service.h> +#include <Core/Util/Log.h> +#include <Core/Util/Util.h> +#include "PeriodChanger.h" + +#define UPDATE_PERIOD_MIN 1800.0f +#define UPDATE_PERIOD_HOUR 60.0 * 60.0 +#define U_(str) dgettext("web-provider", str) + +namespace Service { + +Evas_Object* PeriodChanger::s_window = NULL; +bool PeriodChanger::s_isPopupOpened = false; + +static const char * const TEXT_POPUP_TITLE = "IDS_CLOCK_BODY_UPDATE_INTERVAL"; +static const char * const TEXT_POPUP_CANCEL_BUTTON = "IDS_ST_BUTTON_CANCEL"; +static const char * const TEXT_POPUP_UPDATE_PERIOD_1 ="IDS_ST_BODY_1_HOUR"; +static const char * const TEXT_POPUP_UPDATE_PERIOD_3 ="IDS_ST_BODY_3HOURS"; +static const char * const TEXT_POPUP_UPDATE_PERIOD_6 ="IDS_ST_BODY_6_HOURS_TMO"; +static const char * const TEXT_POPUP_UPDATE_PERIOD_12 ="IDS_ST_BODY_12_HOURS"; +static const char * const TEXT_POPUP_UPDATE_PERIOD_NEVER ="IDS_ST_BODY_NEVER"; +static const char * const MO_INSTALL_DIR = "/usr/share/res/locale"; +static const char * const MO_PROJECT_NAME = "web-provider"; + +PeriodChanger::PeriodChanger( + std::string& boxId, std::string& instanceId, + double currentPeriod, double requestedPeriod) + : m_boxId(boxId) + , m_instanceId(instanceId) + , m_currentPeriod(currentPeriod) + , m_requestedPeriod(requestedPeriod) + , m_hour() +{ + LogD("enter"); +} + +PeriodChanger::~PeriodChanger() +{ + LogD("enter"); +} + +bool PeriodChanger::change() +{ + LogD("enter"); + + if (m_requestedPeriod < 0) { + showPeriodPopup(); + return true; + } + + double newPeriod; + if (m_requestedPeriod == 0) { + newPeriod = 0.0; + } else if (m_requestedPeriod > 0) { + if (m_requestedPeriod >= UPDATE_PERIOD_MIN) { + newPeriod = m_requestedPeriod; + } else { + newPeriod = UPDATE_PERIOD_MIN; + } + } else { + LogD("negative value can't be handled here"); + newPeriod = 0.0; + } + + // after selecting one among period list, the following should be executed + return requestToPlatform(newPeriod); +} + +void PeriodChanger::showPeriodPopup() +{ + LogD("enter"); + + Evas_Object* window = createWindow(); + Evas_Object* periodList = elm_list_add(window); + + if (!periodList) { + LogD("failed to add elm_list_add"); + } + elm_list_mode_set(periodList, ELM_LIST_EXPAND); + bindtextdomain(MO_PROJECT_NAME, MO_INSTALL_DIR); + setPopupListData(); + // TODO Language ID should be used, not static string + for(unsigned int i = 0 ; i < sizeof(m_hour) / sizeof(PopupListData); i++) { + m_hour[i].radio = elm_radio_add(periodList); + elm_radio_state_value_set(m_hour[i].radio, + m_currentPeriod == m_hour[i].newPeriod ? EINA_FALSE : EINA_TRUE); + elm_list_item_append(periodList, + m_hour[i].period, + m_hour[i].radio, + NULL, + selectPeriodCallback, &m_hour[i]); + } + + // create popup + Evas_Object *popup = elm_popup_add(window); + if (!popup) { + LogD("failed to add elm_popup_add"); + return; + } + elm_object_style_set(popup, "popup-item list"); + evas_object_size_hint_weight_set(popup, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + elm_object_part_text_set(popup, "title,text", U_(TEXT_POPUP_TITLE)); + elm_object_content_set(popup, periodList); + evas_object_show(popup); + Evas_Object* cancelButton = elm_button_add(popup); + if (!cancelButton) { + LogD("failed to add elm_button_add"); + return; + } + // TODO Language ID should be used, not static string + elm_object_text_set(cancelButton, U_(TEXT_POPUP_CANCEL_BUTTON)); + elm_object_style_set(cancelButton, "popup_button/default"); + elm_object_part_content_set(popup, "button1", cancelButton); + evas_object_show(cancelButton); + evas_object_smart_callback_add(cancelButton, "clicked", cancelButtonCallback, this); + + // register back key callback + ea_object_event_callback_add( + popup, EA_CALLBACK_BACK, + pressHardwareBackKeyCallback, this); +} + +void PeriodChanger::destroyPeriodPopup(Evas_Object *obj) +{ + LogD("enter"); + Evas_Object* parent = elm_object_parent_widget_get(obj); + Evas_Object* popup = elm_popup_add(parent); + while (parent) { + const char* type = elm_object_widget_type_get(parent); + if (type && !strcmp(type, elm_object_widget_type_get(popup))) { + evas_object_del(parent); + break; + } + parent = elm_object_parent_widget_get(parent); + } + + // register back key callback + ea_object_event_callback_del(popup, EA_CALLBACK_BACK, pressHardwareBackKeyCallback); + evas_object_del(popup); + destroyWindow(); +} + +void PeriodChanger::setPopupListData() +{ + LogD("enter"); + + m_hour[0].periodChanger = this; + m_hour[0].newPeriod = 1.0 * UPDATE_PERIOD_HOUR; + m_hour[0].period = U_(TEXT_POPUP_UPDATE_PERIOD_1); + + m_hour[1].periodChanger = this; + m_hour[1].newPeriod = 3.0 * UPDATE_PERIOD_HOUR; + m_hour[1].period = U_(TEXT_POPUP_UPDATE_PERIOD_3); + + m_hour[2].periodChanger = this; + m_hour[2].newPeriod = 6.0 * UPDATE_PERIOD_HOUR; + m_hour[2].period = U_(TEXT_POPUP_UPDATE_PERIOD_6); + + m_hour[3].periodChanger = this; + m_hour[3].newPeriod = 12.0 * UPDATE_PERIOD_HOUR; + m_hour[3].period = U_(TEXT_POPUP_UPDATE_PERIOD_12); + + m_hour[4].periodChanger = this; + m_hour[4].newPeriod = 0.0; + m_hour[4].period = U_(TEXT_POPUP_UPDATE_PERIOD_NEVER); + +} + +bool PeriodChanger::requestToPlatform(double newPeriod) +{ + int ret = livebox_service_change_period( + m_boxId.c_str(), m_instanceId.c_str(), newPeriod); + + if (ret < 0) { + LogD("during update period, error occurs"); + return false; + } + + LogD("Instance's period is set to %f", newPeriod); + return true; +} + + +Evas_Object* PeriodChanger::createWindow() +{ + LogD("enter"); + + if (s_window) { + evas_object_show(s_window); + elm_win_raise(s_window); + return s_window; + } + + s_window = elm_win_add(NULL, "web-provider-popup", ELM_WIN_BASIC); + elm_win_alpha_set(s_window, EINA_TRUE); + elm_win_title_set(s_window, "change update period"); + elm_win_borderless_set(s_window, EINA_TRUE); + + int width = 0; + int height = 0; + ecore_x_window_size_get(ecore_x_window_root_first_get(), &width, &height); + evas_object_resize(s_window, width, height); + elm_win_indicator_mode_set(s_window, ELM_WIN_INDICATOR_SHOW); + + evas_object_color_set(s_window, 255, 255, 255, 0); + evas_object_show(s_window); + s_isPopupOpened = true; + return s_window; +} + +void PeriodChanger::destroyWindow() +{ + LogD("enter"); + + if (!s_window) { + return; + } + evas_object_del(s_window); + s_window = NULL; + s_isPopupOpened = false; +} + +void PeriodChanger::selectPeriodCallback(void *data, Evas_Object *obj, void *event_info) +{ + LogD("enter"); + UNUSED_PARAM(obj); + UNUSED_PARAM(event_info); + + PopupListData* popupData = static_cast<PopupListData*>(data); + + LogD("Update period is set to %f", popupData->newPeriod); + popupData->periodChanger->requestToPlatform(popupData->newPeriod); + ecore_idler_add(popupDestroyIdlerCallback, popupData); +} + +void PeriodChanger::cancelButtonCallback(void *data, Evas_Object *obj, void *event_info) +{ + LogD("enter"); + UNUSED_PARAM(event_info); + + PeriodChanger* This = static_cast<PeriodChanger*>(data); + This->destroyPeriodPopup(obj); +} + +void PeriodChanger::pressHardwareBackKeyCallback(void *data, Evas_Object *obj, void *event_info) +{ + LogD("enter"); + UNUSED_PARAM(event_info); + + PeriodChanger* This = static_cast<PeriodChanger*>(data); + This->destroyPeriodPopup(obj); +} + +Eina_Bool PeriodChanger::popupDestroyIdlerCallback(void *data) +{ + LogD("enter"); + PopupListData* popupData = static_cast<PopupListData*>(data); + popupData->periodChanger->destroyPeriodPopup(popupData->radio); + return ECORE_CALLBACK_CANCEL; +} +} // Service diff --git a/src_mobile/Core/Service/PeriodChanger.h b/src_mobile/Core/Service/PeriodChanger.h new file mode 100755 index 0000000..b8902b0 --- /dev/null +++ b/src_mobile/Core/Service/PeriodChanger.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file PeriodChanger.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef PERIOD_CHNAGER_H +#define PERIOD_CHNAGER_H + +#include <string> +#include <memory> +#include <Evas.h> + +namespace Service { +class PeriodChanger; +typedef std::shared_ptr<PeriodChanger> PeriodChangerPtr; + +class PeriodChanger { + public: + static PeriodChangerPtr create( + std::string& boxId, std::string& instanceId, + double currentPeriod, double requestedPeriod) + { + return PeriodChangerPtr( + new PeriodChanger(boxId, instanceId, currentPeriod, requestedPeriod)); + } + bool change(); + static bool isPopupOpened() { return s_isPopupOpened; }; + ~PeriodChanger(); + + private: + void showPeriodPopup(); + void destroyPeriodPopup(Evas_Object *obj); + void setPopupListData(); + bool requestToPlatform(double newPeriod); + static Evas_Object* createWindow(); + static void destroyWindow(); + + static void selectPeriodCallback(void *data, Evas_Object *obj, void *event_info); + static void cancelButtonCallback(void *data, Evas_Object *obj, void *event_info); + static void pressHardwareBackKeyCallback(void *data, Evas_Object *obj, void *event_info); + static Eina_Bool popupDestroyIdlerCallback(void *data); + + PeriodChanger( + std::string& boxId, std::string& instanceId, + double currentPeriod, double requestedPeriod); + + static Evas_Object* s_window; + std::string m_boxId; + std::string m_instanceId; + float m_currentPeriod; + float m_requestedPeriod; + static bool s_isPopupOpened; + + struct PopupListData { + PeriodChanger* periodChanger; + double newPeriod; + const char* period; + Evas_Object* radio; + }; + + PopupListData m_hour[5]; +}; +} // Service + +#endif // PERIOD_CHNAGER_H diff --git a/src_mobile/Core/Service/ScrollHolder.cpp b/src_mobile/Core/Service/ScrollHolder.cpp new file mode 100644 index 0000000..3435ff7 --- /dev/null +++ b/src_mobile/Core/Service/ScrollHolder.cpp @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file ScrollHolder.cpp + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ + +#include <string> +#include <provider.h> +#include <Core/Util/Log.h> + +namespace Service { +namespace ScrollHolder { + +void holdHorizontalScroll(std::string& boxId, std::string& instanceId, bool start) +{ + LogD("enter"); + + if (start) { + LogD("scroll start"); + provider_send_hold_scroll(boxId.c_str(), instanceId.c_str(), 1); + } else { + LogD("scroll stop"); + provider_send_hold_scroll(boxId.c_str(), instanceId.c_str(), 0); + } +} + +} // AppControl +} // Service diff --git a/src_mobile/Core/Service/ScrollHolder.h b/src_mobile/Core/Service/ScrollHolder.h new file mode 100644 index 0000000..a7373b7 --- /dev/null +++ b/src_mobile/Core/Service/ScrollHolder.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file ScrollHolder.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ + +#include <string> + +namespace Service { +namespace ScrollHolder { + +void holdHorizontalScroll(std::string& boxId, std::string& instanceId, bool start); + +} +} // Service diff --git a/src_mobile/Core/Util/CMakeLists.txt b/src_mobile/Core/Util/CMakeLists.txt new file mode 100644 index 0000000..c7c5503 --- /dev/null +++ b/src_mobile/Core/Util/CMakeLists.txt @@ -0,0 +1,60 @@ +# Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved +# +# Licensed under the Flora License, Version 1.1 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://floralicense.org/license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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) + +SET(TARGET_NAME ${TARGET_CORE_UTIL}) +SET(DEPS ${TARGET_NAME}_DEPS) + +PKG_CHECK_MODULES(${DEPS} + dlog + REQUIRED +) +ADD_DEFINITIONS(${${DEPS}_CFLAGS}) + +SET(SRCS + ${CMAKE_CURRENT_SOURCE_DIR}/Log.cpp +) + +SET(HEADERS + ${${DEPS}_INCLUDE_DIRS} + ${CMAKE_CURRENT_SOURCE_DIR} +) + +INCLUDE_DIRECTORIES(${HEADERS}) + +ADD_LIBRARY(${TARGET_NAME} STATIC ${SRCS}) + +SET_TARGET_PROPERTIES(${TARGET_NAME} PROPERTIES + COMPILE_FLAGS -fPIC + LINK_FLAGS "-Wl,--as-needed -Wl,--hash-style=both" +) + +SET_TARGET_PROPERTIES(${TARGET_NAME} + PROPERTIES + SOVERSION ${CMAKE_PROJECT_API_VERSION} + VERSION ${CMAKE_PROJECT_VERSION} +) + +TARGET_LINK_LIBRARIES(${TARGET_NAME} + ${${DEPS}_LIBRARIES} +) + +INCLUDE_DIRECTORIES(${HEADERS}) +GET_FILENAME_COMPONENT(CURRENT_DIR_NAME ${CMAKE_CURRENT_SOURCE_DIR} NAME) +GET_FILENAME_COMPONENT(PARENT_DIR_ABSOLUTE_PATH ${CMAKE_CURRENT_SOURCE_DIR} PATH) +GET_FILENAME_COMPONENT(PARENT_DIR_NAME ${PARENT_DIR_ABSOLUTE_PATH} NAME) + +INSTALL_FILE(Noncopyable.h include/${PROJECT_NAME}/${PARENT_DIR_NAME}/${CURRENT_DIR_NAME}) +INSTALL_FILE(Log.h include/${PROJECT_NAME}/${PARENT_DIR_NAME}/${CURRENT_DIR_NAME}) diff --git a/src_mobile/Core/Util/ITimer.h b/src_mobile/Core/Util/ITimer.h new file mode 100644 index 0000000..c6595cb --- /dev/null +++ b/src_mobile/Core/Util/ITimer.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file ITimer.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef I_TIMER_H +#define I_TIMER_H + +#include <memory> + +class ITimer { + public: + virtual void start() = 0; + virtual void stop() = 0; + virtual void resume() = 0; + virtual void pause() = 0; + virtual void restart() = 0; + virtual void setPeriod(float period) = 0; + + virtual ~ITimer() {}; +}; + +typedef std::shared_ptr<ITimer> ITimerPtr; + +#endif // I_TIMER_H diff --git a/src_mobile/Core/Util/Log.cpp b/src_mobile/Core/Util/Log.cpp new file mode 100644 index 0000000..34712ac --- /dev/null +++ b/src_mobile/Core/Util/Log.cpp @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file Log.cpp + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ diff --git a/src_mobile/Core/Util/Log.h b/src_mobile/Core/Util/Log.h new file mode 100644 index 0000000..ff649f7 --- /dev/null +++ b/src_mobile/Core/Util/Log.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file Log.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef LOG_H +#define LOG_H + +#include <dlog.h> +#include <string.h> + +#define FILE_NAME ((strrchr(__FILE__, '/') ? : __FILE__- 1) + 1) + +//#define LogW(fmt, arg...) LOGW( "[[32m%s:%d[0m:%s] " fmt "\n", __FILE__, __LINE__, __func__, ##arg) +//#define LogD(fmt, arg...) LOGD( "[[32m%s:%d[0m:%s] " fmt "\n", __FILE__, __LINE__, __func__, ##arg) +//#define LogE(fmt, arg...) LOGE( "[[32m%s:%d[0m:%s] " fmt "\n", __FILE__, __LINE__, __func__, ##arg) + +#define LogW(fmt, arg...) LOGW( fmt "\n", ##arg) +#define LogD(fmt, arg...) LOGD( fmt "\n", ##arg) +#define LogE(fmt, arg...) LOGE( fmt "\n", ##arg) +#endif // LOG_H diff --git a/src_mobile/Core/Util/Noncopyable.h b/src_mobile/Core/Util/Noncopyable.h new file mode 100644 index 0000000..accdd53 --- /dev/null +++ b/src_mobile/Core/Util/Noncopyable.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file Noncopyable.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef NONCOPYABLE_H +#define NONCOPYABLE_H + +class Noncopyable { + protected: + Noncopyable() {}; + ~Noncopyable() {}; + + private: + Noncopyable(const Noncopyable&); + Noncopyable& operator=(const Noncopyable&); +}; + +#endif // NONCOPYABLE_H diff --git a/src_mobile/Core/Util/Util.h b/src_mobile/Core/Util/Util.h new file mode 100644 index 0000000..b2c310d --- /dev/null +++ b/src_mobile/Core/Util/Util.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file Util.h + * @author Soo-Hyun Choi (sh9.choi@samsung.com) + */ +#ifndef UTIL_H +#define UTIL_H + +#define UNUSED_PARAM(expr) (void)(expr) + +#endif // UTIL_H diff --git a/src_mobile/Core/View/CMakeLists.txt b/src_mobile/Core/View/CMakeLists.txt new file mode 100644 index 0000000..083a34b --- /dev/null +++ b/src_mobile/Core/View/CMakeLists.txt @@ -0,0 +1,66 @@ +# Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved +# +# Licensed under the Flora License, Version 1.1 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://floralicense.org/license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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) + +SET(TARGET_NAME ${TARGET_CORE_VIEW}) +SET(DEPS ${TARGET_NAME}_DEPS) + +PKG_CHECK_MODULES(${DEPS} + evas + eina + ewebkit2 + dlog + REQUIRED +) +ADD_DEFINITIONS(${${DEPS}_CFLAGS}) + +SET(SRCS + ${CMAKE_CURRENT_SOURCE_DIR}/WebView.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/PdHelper.cpp +) + +SET(HEADERS + ${${DEPS}_INCLUDE_DIRS} + ${CMAKE_CURRENT_SOURCE_DIR} +) +INCLUDE_DIRECTORIES(${HEADERS}) + +ADD_LIBRARY(${TARGET_NAME} STATIC ${SRCS}) + +SET_TARGET_PROPERTIES(${TARGET_NAME} PROPERTIES + COMPILE_FLAGS -fPIC + LINK_FLAGS "-Wl,--as-needed -Wl,--hash-style=both" +) + +SET_TARGET_PROPERTIES(${TARGET_NAME} + PROPERTIES + SOVERSION ${CMAKE_PROJECT_API_VERSION} + VERSION ${CMAKE_PROJECT_VERSION} +) + +TARGET_LINK_LIBRARIES(${TARGET_NAME} + ${${DEPS}_LIBRARIES} +) + +GET_FILENAME_COMPONENT(CURRENT_DIR_NAME ${CMAKE_CURRENT_SOURCE_DIR} NAME) +GET_FILENAME_COMPONENT(PARENT_DIR_ABSOLUTE_PATH ${CMAKE_CURRENT_SOURCE_DIR} PATH) +GET_FILENAME_COMPONENT(PARENT_DIR_NAME ${PARENT_DIR_ABSOLUTE_PATH} NAME) + +INSTALL_FILE(IRenderView.h include/${PROJECT_NAME}/${PARENT_DIR_NAME}/${CURRENT_DIR_NAME}) +INSTALL_FILE(IPdHelper.h include/${PROJECT_NAME}/${PARENT_DIR_NAME}/${CURRENT_DIR_NAME}) +INSTALL_FILE(PdHelper.h include/${PROJECT_NAME}/${PARENT_DIR_NAME}/${CURRENT_DIR_NAME}) +INSTALL_FILE(IWebView.h include/${PROJECT_NAME}/${PARENT_DIR_NAME}/${CURRENT_DIR_NAME}) +INSTALL_FILE(WebView.h include/${PROJECT_NAME}/${PARENT_DIR_NAME}/${CURRENT_DIR_NAME}) +INSTALL_FILE(injection.js /usr/share/${PROJECT_NAME}) diff --git a/src_mobile/Core/View/IPdHelper.h b/src_mobile/Core/View/IPdHelper.h new file mode 100644 index 0000000..b2f7db9 --- /dev/null +++ b/src_mobile/Core/View/IPdHelper.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file IPdHelper.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef I_PD_HELPER_H +#define I_PD_HELPER_H + +#include <Evas.h> +#include <memory> + +class IPdHelper { + public: + virtual void startOpen() = 0; + virtual void finishOpen(Evas_Object* child) = 0; + virtual void close() = 0; + virtual void setBoxWebView(Evas_Object* webview) = 0; + virtual void setPdWebView(Evas_Object* webview) = 0; + virtual Evas_Object* getBoxWebView() const = 0; + virtual Evas_Object* getPdWebView() const = 0; + virtual Evas* getPdCanvas() const = 0; + virtual bool isPdOpened() const = 0; +}; + +typedef std::shared_ptr<IPdHelper> IPdHelperPtr; + +#endif // I_PD_HELPER_H diff --git a/src_mobile/Core/View/IRenderView.h b/src_mobile/Core/View/IRenderView.h new file mode 100644 index 0000000..9e24ed0 --- /dev/null +++ b/src_mobile/Core/View/IRenderView.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file IRenderView.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef I_RENDER_VIEW_H +#define I_RENDER_VIEW_H + +#include <string> +#include <memory> +#include <Evas.h> + +struct RenderInfo { + int width; + int height; + Evas_Object* window; + std::string defaultUrlParams; +}; +typedef std::shared_ptr<RenderInfo> RenderInfoPtr; + +class IRenderView { + public: + enum UrlType { + URL_TYPE_BOX, + URL_TYPE_PD + }; + virtual void showBox(RenderInfoPtr boxRenderInfo) = 0; + virtual void hideBox() = 0; + virtual void pauseBox() = 0; + virtual void resumeBox() = 0; + virtual void showPd(RenderInfoPtr pdRenderInfo, RenderInfoPtr boxRenderInfo) = 0; + virtual void hidePd() = 0; + virtual Evas_Object* getBoxWebView() = 0; + virtual Evas_Object* getPdWebView() = 0; + virtual ~IRenderView() {}; +}; +typedef std::shared_ptr<IRenderView> IRenderViewPtr; + +#endif // I_RENDER_VIEW_H diff --git a/src_mobile/Core/View/IWebView.h b/src_mobile/Core/View/IWebView.h new file mode 100644 index 0000000..1260345 --- /dev/null +++ b/src_mobile/Core/View/IWebView.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file IWebView.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef I_WEB_VIEW_H +#define I_WEB_VIEW_H + +#include <string> +#include <memory> + +class IWebView { + public: + typedef void (*WebViewCallback)(void* data, void* eventInfo); + virtual bool show( + std::string& startUrl, int width, int height, + WebViewCallback didCreateBaseWebView, void* data) = 0; + virtual bool hide() = 0; + virtual bool suspend() = 0; + virtual bool resume() = 0; + virtual bool setBasicSetting(Evas_Object* webview) = 0; + virtual bool unsetBasicSetting(Evas_Object* webview) = 0; + + public: + virtual ~IWebView() {}; +}; + +typedef std::shared_ptr<IWebView> IWebViewPtr; + +#endif // I_WEB_VIEW_H diff --git a/src_mobile/Core/View/PdHelper.cpp b/src_mobile/Core/View/PdHelper.cpp new file mode 100644 index 0000000..ba57c8f --- /dev/null +++ b/src_mobile/Core/View/PdHelper.cpp @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file PdHelper.cpp + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#include <string> +#include <Evas.h> +#include <ewk_view.h> +#include <Core/Util/Log.h> +#include <Core/Util/Util.h> +#include "IRenderView.h" +#include "IPdHelper.h" +#include "PdHelper.h" + +PdHelper::PdHelper(RenderInfoPtr pdRenderInfo, std::string pdStartUrl) + : m_boxWebView() + , m_pdWebView() + , m_pdRenderInfo(pdRenderInfo) + , m_startUrl(pdStartUrl) + , m_opened(false) +{ +} + +PdHelper::~PdHelper() +{ +} + +void PdHelper::startOpen() +{ + LogD("enter"); + if (!m_boxWebView) { + return; + } + + //make javascript string for pd + std::string script = "var pdWindow = window.open(\""; + script += validateUrl(m_startUrl); + script += "\", \"_blank\");"; + + // execute javascript for opening new webview for pd + LogD("executed script: %s", script.c_str()); + ewk_view_script_execute( + m_boxWebView, script.c_str(), executeScriptCallback, this); +} + +void PdHelper::finishOpen(Evas_Object* child) +{ + LogD("enter"); + + // pd webview set and resize + m_pdWebView = child; + evas_object_resize(m_pdWebView, m_pdRenderInfo->width, m_pdRenderInfo->height); + m_opened = true; +} + +void PdHelper::close() +{ + LogD("enter"); +} + +void PdHelper::setBoxWebView(Evas_Object* webview) +{ + LogD("enter"); + m_boxWebView = webview; +} + +void PdHelper::setPdWebView(Evas_Object* webview) +{ + LogD("enter"); + m_pdWebView = webview; +} + +Evas_Object* PdHelper::getBoxWebView() const +{ + LogD("enter"); + return m_boxWebView; +} + +Evas_Object* PdHelper::getPdWebView() const +{ + LogD("enter"); + return m_pdWebView; +} + +Evas* PdHelper::getPdCanvas() const +{ + LogD("enter"); + return evas_object_evas_get(m_pdRenderInfo->window); +} + +bool PdHelper::isPdOpened() const +{ + LogD("enter"); + return m_opened; +} + +void PdHelper::didExecuteScript(Evas_Object* webview, std::string& result) +{ + LogD("enter"); + UNUSED_PARAM(webview); + LogD("javascript execution result: %s", result.c_str()); +} + +std::string PdHelper::validateUrl(std::string& url) +{ + LogD("enter"); + + if (url.empty()) { + return std::string(); + } + + if((!url.compare(0, 4, "http")) || + (!url.compare(0, 5, "https")) || + (!url.compare(0, 4, "file"))) + { + return url; + } + + std::string newUrl("file://"); + newUrl += url; + return newUrl; +} + +void PdHelper::executeScriptCallback( + Evas_Object* webview, const char* result, void* data) +{ + LogD("enter"); + + PdHelper* This = static_cast<PdHelper*>(data); + std::string resultStr(result ? result : "null"); + This->didExecuteScript(webview, resultStr); +} + diff --git a/src_mobile/Core/View/PdHelper.h b/src_mobile/Core/View/PdHelper.h new file mode 100644 index 0000000..6879ba3 --- /dev/null +++ b/src_mobile/Core/View/PdHelper.h @@ -0,0 +1,69 @@ + +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file PdHelper.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ + +#ifndef PD_HELPER_H +#define PD_HELPER_H + +#include <string> +#include <Evas.h> +#include "IRenderView.h" +#include "IPdHelper.h" + +#define EXPORT_CLASS __attribute__ ((visibility("default")) + +class EXPORT_CLASS PdHelper: public IPdHelper { + public: + static IPdHelperPtr create( + RenderInfoPtr pdRenderInfo, + std::string pdStartUrl) + { + return IPdHelperPtr(new PdHelper(pdRenderInfo, pdStartUrl)); + } + virtual void startOpen(); + virtual void finishOpen(Evas_Object* child); + virtual void close(); + virtual void setBoxWebView(Evas_Object* webview); + virtual void setPdWebView(Evas_Object* webview); + virtual Evas_Object* getBoxWebView() const; + virtual Evas_Object* getPdWebView() const; + virtual Evas* getPdCanvas() const; + virtual bool isPdOpened() const; + virtual ~PdHelper(); + + private: + virtual void didExecuteScript(Evas_Object* webview, std::string& result); + + std::string validateUrl(std::string& url); + static void executeScriptCallback( + Evas_Object* webview, const char* result, void* data); + + PdHelper(RenderInfoPtr pdRenderInfo, std::string pdStartUrl); + + //members + Evas_Object* m_boxWebView; + Evas_Object* m_pdWebView; + RenderInfoPtr m_pdRenderInfo; + std::string m_startUrl; + bool m_opened; +}; + +#endif // PD_HELPER_H + diff --git a/src_mobile/Core/View/WebView.cpp b/src_mobile/Core/View/WebView.cpp new file mode 100755 index 0000000..4e58d55 --- /dev/null +++ b/src_mobile/Core/View/WebView.cpp @@ -0,0 +1,847 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file WebView.cpp + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#include <string> +#include <fstream> +#include <streambuf> +#include <Evas.h> +#include <Eina.h> +#include <ewk_context.h> +#include <ewk_view.h> +#include <ewk_policy_decision.h> +#include <Core/Util/Log.h> +#include <Core/Util/Util.h> +#include <Core/Service/AppControl.h> +#include "WebView.h" + +// injection javascript file regarding creating js object used by box and pd +static const std::string injectionFile("/usr/share/web-provider/injection.js"); + +std::map<const std::string, const Evas_Smart_Cb> WebView::m_smartCallbacksMap = +{ + {"load,started", WebView::loadStartedCallback}, + {"load,finished", WebView::loadFinishedCallback}, + {"title,changed", WebView::titleChangedCallback}, + {"uri,changed", WebView::uriChangedCallback}, + {"load,progress", WebView::loadProgressCallback}, + {"load,progress,finished", WebView::loadProgressFinishedCallback}, + {"process,crashed", WebView::processCrashedCallback}, + {"create,window", WebView::createWindowCallback}, + {"close,window", WebView::closeWindowCallback}, + {"policy,navigation,decide", WebView::policyNavigationDecideCallback}, + {"policy,newwindow,decide", WebView::policyNewWindowDecideCallback}, + {"policy,response,decide", WebView::pageResponseDecideCallback}, + {"contextmenu,customize", WebView::contextmenuCustomizeCallback}, + {"form,submit", WebView::formSubmitCallback}, + {"request,geolocation,permission", WebView::geolocationPermissionRequestCallback}, + {"notification,show", WebView::notificationShowCallback}, + {"notification,cancel", WebView::notificationCancelCallback}, + {"notification,permission,request", WebView::notificationPermissionRequestCallback}, + {"database,quota,exceeded", WebView::databaseUsagePermissionRequestCallback}, + {"filesystem,permission,request", WebView::fileSystemPermissionRequestCallback}, + {"fullscreen,enterfullscreen", WebView::enterFullscreenCallback}, + {"fullscreen,exitfullscreen", WebView::exitFullscreenCallback}, + {"inputmethod,changed", WebView::imeChangedCallback}, + {"editorclient,ime,opened", WebView::imeOpenedCallback}, + {"editorclient,ime,closed", WebView::imeClosedCallback}, + {"usermedia,permission,request", WebView::usermediaPermissionRequestCallback}, + {"protocolhandler,registration,requested", WebView::protocolHandlerRegistrationCallback}, + {"protocolhandler,isregistered", WebView::protocolHandlerIsRegisteredCallback}, + {"protocolhandler,unregistration,requested", WebView::protocolHandlerUnregistrationCallback}, + {"contenthandler,registration,requested", WebView::contentHandlerRegistrationCallback}, + {"contenthandler,isregistered", WebView::contentHandlerIsRegisteredCallback}, + {"contenthandler,unregistration,requested", WebView::contentHandlerUnregistrationCallback}, + {"request,certificate,confirm", WebView::certificateConfirmRequestCallback} +}; + +WebView::WebView(Evas_Object* win, Ewk_Context* ewkContext) + : m_topWebview(NULL) + , m_win(win) + , m_ewkContext(ewkContext) +{ +} + +WebView::~WebView() +{ +} + +bool WebView::show( + std::string& startUrl, int width, int height, + WebViewCallback didCreateBaseWebView, void* data) +{ + LogD("enter"); + if (!m_topWebview) { + m_topWebview = ewk_view_add_with_context( + evas_object_evas_get(m_win), m_ewkContext); + if (!setBasicSetting(m_topWebview)) { + return false; + } + } + + // inform base webview to caller + if (didCreateBaseWebView) { + didCreateBaseWebView(data, static_cast<void*>(m_topWebview)); + } + + // check scheme of url + std::string url = validateUrl(startUrl); + LogD("load: %s", url.c_str()); + evas_object_resize(m_topWebview, width, height); + evas_object_show(m_topWebview); + ewk_view_url_set(m_topWebview, url.c_str()); + + return true; +} + +bool WebView::hide() +{ + LogD("enter"); + + // TODO If created webviews are managed by WebView Class, + // add code regarding created all webviews + if (!unsetBasicSetting(m_topWebview)) { + return false; + } + if(!m_topWebview) { + return false; + } + evas_object_del(m_topWebview); + m_topWebview = NULL; + + return true; +} + +bool WebView::suspend() +{ + LogD("enter"); + ewk_view_page_visibility_state_set( + m_topWebview, EWK_PAGE_VISIBILITY_STATE_HIDDEN, EINA_FALSE); + ewk_view_visibility_set(m_topWebview, EINA_FALSE); + ewk_view_suspend(m_topWebview); + return true; +} + +bool WebView::resume() +{ + LogD("enter"); + ewk_view_resume(m_topWebview); + ewk_view_page_visibility_state_set( + m_topWebview, EWK_PAGE_VISIBILITY_STATE_VISIBLE, EINA_FALSE); + ewk_view_visibility_set(m_topWebview, EINA_TRUE); + return true; +} + +bool WebView::setBasicSetting(Evas_Object* webview) +{ + LogD("enter"); + + if (!webview) { + return false; + } + + for (auto it = m_smartCallbacksMap.begin(); + it != m_smartCallbacksMap.end(); it++) { + evas_object_smart_callback_add( + webview, it->first.c_str(), it->second, this); + } + + // set specific features + Ewk_Settings* setting = ewk_view_settings_get(webview); + // set user agent like WRT, or Browser? + // ewk_view_user_agent_set(webview, "some_ua_string"); + ewk_settings_plugins_enabled_set(setting, EINA_TRUE); + ewk_settings_javascript_enabled_set(setting, EINA_TRUE); + ewk_settings_loads_images_automatically_set(setting, EINA_TRUE); + ewk_settings_auto_fitting_set(setting, EINA_FALSE); + ewk_settings_default_keypad_enabled_set(setting, EINA_FALSE); + + // set visibility + ewk_view_page_visibility_state_set( + webview, EWK_PAGE_VISIBILITY_STATE_VISIBLE, EINA_TRUE); + + evas_object_color_set(webview, 0, 0, 0, 1); + + return true; +} + +bool WebView::unsetBasicSetting(Evas_Object* webview) +{ + LogD("enter"); + + if (!webview) { + return false; + } + + for (auto it = m_smartCallbacksMap.begin(); + it != m_smartCallbacksMap.end(); it++) { + evas_object_smart_callback_del( + m_topWebview, it->first.c_str(), it->second); + } + + return true; +} + +std::string WebView::validateUrl(std::string& url) +{ + LogD("enter"); + + if (url.empty()) { + return std::string(); + } + + if((!url.compare(0, 4, "http")) || + (!url.compare(0, 5, "https")) || + (!url.compare(0, 4, "file"))) + { + return url; + } + + std::string newUrl("file://"); + newUrl += url; + return newUrl; +} + +void WebView::loadStartedCallback( + void* data, Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(eventInfo); + + WebView* This = static_cast<WebView*>(data); + + std::ifstream jsFile(injectionFile); + std::string script((std::istreambuf_iterator<char>(jsFile)), + std::istreambuf_iterator<char>()); + LogD("injected js code: %s", script.c_str()); + + ewk_view_script_execute(obj, script.c_str(), executeScriptCallback, This); + This->didLoadStarted(obj); +} + +void WebView::loadFinishedCallback( + void* data, Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(eventInfo); + + WebView* This = static_cast<WebView*>(data); + This->didLoadFinished(obj); +} + +void WebView::titleChangedCallback( + void* data, Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(eventInfo); + + WebView* This = static_cast<WebView*>(data); + This->didTitleChanged(obj, eventInfo); +} + +void WebView::uriChangedCallback( + void* data, Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(eventInfo); + + WebView* This = static_cast<WebView*>(data); + This->didUriChanged(obj, eventInfo); +} + +void WebView::loadProgressCallback( + void* data, Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(eventInfo); + + WebView* This = static_cast<WebView*>(data); + This->didLoadProgress(obj, eventInfo); +} + +void WebView::loadProgressFinishedCallback( + void* data, Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(eventInfo); + + WebView* This = static_cast<WebView*>(data); + This->didLoadProgressFinished(obj); +} + +void WebView::processCrashedCallback( + void* data, Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(eventInfo); + + WebView* This = static_cast<WebView*>(data); + This->didProcessCrashed(obj); +} + +void WebView::createWindowCallback( + void* data, Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(eventInfo); + + WebView* This = static_cast<WebView*>(data); + This->didCreateWindow(obj, eventInfo); +} + +void WebView::closeWindowCallback( + void* data, Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(eventInfo); + + WebView* This = static_cast<WebView*>(data); + This->didCloseWindow(obj); +} + +void WebView::policyNavigationDecideCallback( + void* data, Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + + WebView* This = static_cast<WebView*>(data); + This->didPolicyNavigationDecide(obj, eventInfo); +} + +void WebView::policyNewWindowDecideCallback( + void* data, Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + + WebView* This = static_cast<WebView*>(data); + This->didPolicyNewWindowDecide(obj, eventInfo); +} + +void WebView::pageResponseDecideCallback( + void* data, Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + + Ewk_Policy_Decision *policyDecision = static_cast<Ewk_Policy_Decision *>(eventInfo); + Ewk_Policy_Decision_Type policyType = ewk_policy_decision_type_get(policyDecision); + std::string url(ewk_policy_decision_url_get(policyDecision)); + std::string cookie(ewk_policy_decision_cookie_get(policyDecision)); + const char* contentType = ewk_policy_decision_response_mime_get(policyDecision); + + switch (policyType) { + case EWK_POLICY_DECISION_USE: + LogD("policy use"); + ewk_policy_decision_use(policyDecision); + break; + + case EWK_POLICY_DECISION_DOWNLOAD: + LogD("policy download: %s, %s, %s", url.c_str(), cookie.c_str(), contentType); + ewk_policy_decision_suspend(policyDecision); + Service::AppControl::launchDownloader(url, cookie); + ewk_policy_decision_ignore(policyDecision); + break; + + case EWK_POLICY_DECISION_IGNORE: + default: + LogD("policy ignore"); + ewk_policy_decision_ignore(policyDecision); + break; + } + + if (policyType == EWK_POLICY_DECISION_DOWNLOAD) { + if (ewk_view_back_possible(obj)) { + ewk_view_back(obj); + } else { + // TODO Add handling code in case that new window is opened + //ecore_idler_add(windowCloseIdlerCallback, data); + } + } + + WebView* This = static_cast<WebView*>(data); + This->didPageResponseDecide(obj); +} + +void WebView::contextmenuCustomizeCallback( + void* data, Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + + WebView* This = static_cast<WebView*>(data); + This->didContextmenuCustomize(obj, eventInfo); +} + +void WebView::formSubmitCallback( + void* data, Evas_Object *obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(eventInfo); + + WebView* This = static_cast<WebView*>(data); + This->didFormSubmit(obj); +} + +void WebView::geolocationPermissionRequestCallback( + void* data, Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + + WebView* This = static_cast<WebView*>(data); + This->didGeolocationPermissionRequest(obj, eventInfo); +} + +void WebView::notificationShowCallback( + void* data, Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + + WebView* This = static_cast<WebView*>(data); + This->didNotificationShow(obj, eventInfo); +} + +void WebView::notificationCancelCallback( + void* data, Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + + WebView* This = static_cast<WebView*>(data); + This->didNotificationCancel(obj, eventInfo); +} + +void WebView::notificationPermissionRequestCallback( + void* data, Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + + WebView* This = static_cast<WebView*>(data); + This->didNotificationPermissionRequest(obj, eventInfo); +} + +void WebView::databaseUsagePermissionRequestCallback( + void* data, Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + + WebView* This = static_cast<WebView*>(data); + This->didDatabaseUsagePermissionRequest(obj, eventInfo); +} + +void WebView::fileSystemPermissionRequestCallback( + void* data, Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + + WebView* This = static_cast<WebView*>(data); + This->didFilesystemPermissionRequest(obj, eventInfo); +} + +void WebView::enterFullscreenCallback( + void* data, Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(eventInfo); + + WebView* This = static_cast<WebView*>(data); + This->didEnterFullscreen(obj); +} + +void WebView::exitFullscreenCallback( + void* data, Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(eventInfo); + + WebView* This = static_cast<WebView*>(data); + This->didExitFullscreen(obj); +} + +void WebView::imeChangedCallback( + void* data, Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + + WebView* This = static_cast<WebView*>(data); + This->didImeChanged(obj, eventInfo); +} + +void WebView::imeOpenedCallback( + void* data, Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(eventInfo); + + WebView* This = static_cast<WebView*>(data); + This->didImeOpened(obj); +} + +void WebView::imeClosedCallback( + void* data, Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(eventInfo); + + WebView* This = static_cast<WebView*>(data); + This->didImeClosed(obj); +} + +void WebView::usermediaPermissionRequestCallback( + void* data, Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + + WebView* This = static_cast<WebView*>(data); + This->didUsermediaPermissionRequest(obj, eventInfo); +} + +void WebView::protocolHandlerRegistrationCallback( + void* data, Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + + WebView* This = static_cast<WebView*>(data); + This->didProtocolHandlerRegistration(obj, eventInfo); +} + +void WebView::protocolHandlerIsRegisteredCallback( + void* data, Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + + WebView* This = static_cast<WebView*>(data); + This->didProtocolHandlerIsRegistered(obj, eventInfo); +} + +void WebView::protocolHandlerUnregistrationCallback( + void* data, Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + + WebView* This = static_cast<WebView*>(data); + This->didProtocolHandlerUnregistration(obj, eventInfo); +} + +void WebView::contentHandlerRegistrationCallback( + void* data, Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + + WebView* This = static_cast<WebView*>(data); + This->didContentHandlerRegistration(obj, eventInfo); +} + +void WebView::contentHandlerIsRegisteredCallback( + void* data, Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + + WebView* This = static_cast<WebView*>(data); + This->didContentHandlerIsRegistered(obj, eventInfo); +} + +void WebView::contentHandlerUnregistrationCallback( + void* data, Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + + WebView* This = static_cast<WebView*>(data); + This->didContentHandlerUnregistration(obj, eventInfo); +} + +void WebView::certificateConfirmRequestCallback( + void* data, Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + + WebView* This = static_cast<WebView*>(data); + This->didCertificateConfirmRequest(obj, eventInfo); +} + +void WebView::didLoadStarted(Evas_Object* obj) +{ + LogD("enter"); + UNUSED_PARAM(obj); + + // This Will be implemented by derived class +} + +void WebView::didLoadFinished(Evas_Object* obj) +{ + LogD("enter"); + UNUSED_PARAM(obj); + // This Will be implemented by derived class +} + +void WebView::didTitleChanged(Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(obj); + UNUSED_PARAM(eventInfo); + + // This Will be implemented by derived class +} + +void WebView::didUriChanged(Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(obj); + UNUSED_PARAM(eventInfo); + // This Will be implemented by derived class +} + +void WebView::didLoadProgress(Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(obj); + UNUSED_PARAM(eventInfo); + // This Will be implemented by derived class +} + +void WebView::didLoadProgressFinished(Evas_Object* obj) +{ + LogD("enter"); + UNUSED_PARAM(obj); + // This Will be implemented by derived class +} + +void WebView::didProcessCrashed(Evas_Object* obj) +{ + LogD("enter"); + UNUSED_PARAM(obj); + // This Will be implemented by derived class +} + +void WebView::didCreateWindow(Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(obj); + UNUSED_PARAM(eventInfo); + // This Will be implemented by derived class +} + +void WebView::didCloseWindow(Evas_Object* obj) +{ + LogD("enter"); + UNUSED_PARAM(obj); + // This Will be implemented by derived class +} + +void WebView::didPolicyNavigationDecide(Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(obj); + UNUSED_PARAM(eventInfo); + // This Will be implemented by derived class +} + +void WebView::didPolicyNewWindowDecide(Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(obj); + UNUSED_PARAM(eventInfo); + // This Will be implemented by derived class +} + +void WebView::didPageResponseDecide(Evas_Object* obj) +{ + LogD("enter"); + UNUSED_PARAM(obj); + // This Will be implemented by derived class +} + +void WebView::didContextmenuCustomize(Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(obj); + UNUSED_PARAM(eventInfo); + // This Will be implemented by derived class +} + +void WebView::didFormSubmit(Evas_Object* obj) +{ + LogD("enter"); + UNUSED_PARAM(obj); + // This Will be implemented by derived class +} + +void WebView::didGeolocationPermissionRequest(Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(obj); + UNUSED_PARAM(eventInfo); + // This Will be implemented by derived class +} + +void WebView::didNotificationShow(Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(obj); + UNUSED_PARAM(eventInfo); + // This Will be implemented by derived class +} + +void WebView::didNotificationCancel(Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(obj); + UNUSED_PARAM(eventInfo); + // This Will be implemented by derived class +} + +void WebView::didNotificationPermissionRequest(Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(obj); + UNUSED_PARAM(eventInfo); + // This Will be implemented by derived class +} + +void WebView::didDatabaseUsagePermissionRequest(Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(obj); + UNUSED_PARAM(eventInfo); + // This Will be implemented by derived class +} + +void WebView::didFilesystemPermissionRequest(Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(obj); + UNUSED_PARAM(eventInfo); + // This Will be implemented by derived class +} + +void WebView::didEnterFullscreen(Evas_Object* obj) +{ + LogD("enter"); + UNUSED_PARAM(obj); + // This Will be implemented by derived class +} + +void WebView::didExitFullscreen(Evas_Object* obj) +{ + LogD("enter"); + UNUSED_PARAM(obj); + // This Will be implemented by derived class +} + +void WebView::didImeChanged(Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(obj); + UNUSED_PARAM(eventInfo); + // This Will be implemented by derived class +} + +void WebView::didImeOpened(Evas_Object* obj) +{ + LogD("enter"); + UNUSED_PARAM(obj); + // This Will be implemented by derived class +} + +void WebView::didImeClosed(Evas_Object* obj) +{ + LogD("enter"); + UNUSED_PARAM(obj); + // This Will be implemented by derived class +} + +void WebView::didUsermediaPermissionRequest(Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(obj); + UNUSED_PARAM(eventInfo); + // This Will be implemented by derived class +} + +void WebView::didProtocolHandlerRegistration(Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(obj); + UNUSED_PARAM(eventInfo); + // This Will be implemented by derived class +} + +void WebView::didProtocolHandlerIsRegistered(Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(obj); + UNUSED_PARAM(eventInfo); + // This Will be implemented by derived class +} + +void WebView::didProtocolHandlerUnregistration(Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(obj); + UNUSED_PARAM(eventInfo); + // This Will be implemented by derived class +} + +void WebView::didContentHandlerRegistration(Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(obj); + UNUSED_PARAM(eventInfo); + // This Will be implemented by derived class +} + +void WebView::didContentHandlerIsRegistered(Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(obj); + UNUSED_PARAM(eventInfo); + // This Will be implemented by derived class +} + +void WebView::didContentHandlerUnregistration(Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(obj); + UNUSED_PARAM(eventInfo); + // This Will be implemented by derived class +} + +void WebView::didCertificateConfirmRequest(Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(obj); + UNUSED_PARAM(eventInfo); + // This Will be implemented by derived class +} + +Eina_Bool WebView::orientationLockCallback( + Evas_Object* obj, Eina_Bool needLock, int orientation, void* data) +{ + LogD("enter"); + UNUSED_PARAM(obj); + UNUSED_PARAM(needLock); + UNUSED_PARAM(orientation); + UNUSED_PARAM(data); + return EINA_TRUE; +} + +void WebView::executeScriptCallback( + Evas_Object* obj, const char* result, void* data) +{ + LogD("enter"); + UNUSED_PARAM(obj); + UNUSED_PARAM(result); + UNUSED_PARAM(data); +} + diff --git a/src_mobile/Core/View/WebView.h b/src_mobile/Core/View/WebView.h new file mode 100644 index 0000000..42945c7 --- /dev/null +++ b/src_mobile/Core/View/WebView.h @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file WebView.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef WEB_VIEW_H +#define WEB_VIEW_H + +#include <string> +#include <map> +#include <Eina.h> +#include <Evas.h> +#include <ewk_context.h> +#include "IWebView.h" + +#define EXPORT_CLASS __attribute__ ((visibility("default")) + +class EXPORT_CLASS WebView: public IWebView { + public: + static IWebViewPtr create(Evas_Object* win, Ewk_Context* ewkContext) + { + if (!win || !ewkContext) { + return IWebViewPtr(); + } + + return IWebViewPtr(new WebView(win, ewkContext)); + } + virtual bool show( + std::string& startUrl, int width, int height, + WebViewCallback didCreateBaseWebView, void* data); + virtual bool hide(); + virtual bool suspend(); + virtual bool resume(); + virtual ~WebView(); + + protected: + bool setBasicSetting(Evas_Object* webview); + bool unsetBasicSetting(Evas_Object* webview); + explicit WebView(Evas_Object* win, Ewk_Context* ewkContext); + + private: + std::string validateUrl(std::string& url); + + // webviw smart callbacks + static void loadStartedCallback( + void* data, Evas_Object* obj, void* eventInfo); + static void loadFinishedCallback( + void* data, Evas_Object* obj, void* eventInfo); + static void titleChangedCallback( + void* data, Evas_Object* obj, void* eventInfo); + static void uriChangedCallback( + void* data, Evas_Object* obj, void* eventInfo); + static void loadProgressCallback( + void* data, Evas_Object* obj, void* eventInfo); + static void loadProgressFinishedCallback( + void* data, Evas_Object* obj, void* eventInfo); + static void processCrashedCallback( + void* data, Evas_Object* obj, void* eventInfo); + static void createWindowCallback( + void* data, Evas_Object* obj, void* eventInfo); + static void closeWindowCallback( + void* data, Evas_Object* obj, void* eventInfo); + static void policyNavigationDecideCallback( + void* data, Evas_Object* obj, void* eventInfo); + static void policyNewWindowDecideCallback( + void* data, Evas_Object* obj, void* eventInfo); + static void pageResponseDecideCallback( + void* data, Evas_Object* obj, void* eventInfo); + static void contextmenuCustomizeCallback( + void* data, Evas_Object* obj, void* eventInfo); + static void formSubmitCallback( + void *data, Evas_Object *obj, void *eventInfo); + static void geolocationPermissionRequestCallback( + void* data, Evas_Object* obj, void* eventInfo); + static void notificationShowCallback( + void* data, Evas_Object* obj, void* eventInfo); + static void notificationCancelCallback( + void* data, Evas_Object* obj, void* eventInfo); + static void notificationPermissionRequestCallback( + void* data, Evas_Object* obj, void* eventInfo); + static void databaseUsagePermissionRequestCallback( + void* data, Evas_Object* obj, void* eventInfo); + static void fileSystemPermissionRequestCallback( + void* data, Evas_Object* obj, void* eventInfo); + static void enterFullscreenCallback( + void* data, Evas_Object* obj, void* eventInfo); + static void exitFullscreenCallback( + void* data, Evas_Object* obj, void* eventInfo); + static void imeChangedCallback( + void* data, Evas_Object* obj, void* eventInfo); + static void imeOpenedCallback( + void* data, Evas_Object* obj, void* eventInfo); + static void imeClosedCallback( + void* data, Evas_Object* obj, void* eventInfo); + static void usermediaPermissionRequestCallback( + void* data, Evas_Object* obj, void* eventInfo); + static void protocolHandlerRegistrationCallback( + void* data, Evas_Object* obj, void* eventInfo); + static void protocolHandlerIsRegisteredCallback( + void* data, Evas_Object* obj, void* eventInfo); + static void protocolHandlerUnregistrationCallback( + void* data, Evas_Object* obj, void* eventInfo); + static void contentHandlerRegistrationCallback( + void* data, Evas_Object* obj, void* eventInfo); + static void contentHandlerIsRegisteredCallback( + void* data, Evas_Object* obj, void* eventInfo); + static void contentHandlerUnregistrationCallback( + void* data, Evas_Object* obj, void* eventInfo); + static void certificateConfirmRequestCallback( + void* data, Evas_Object* obj, void* eventInfo); + + // internal implementation for smart callbacks + virtual void didLoadStarted(Evas_Object* obj); + virtual void didLoadFinished(Evas_Object* obj); + virtual void didTitleChanged(Evas_Object* obj, void* eventInfo); + virtual void didUriChanged(Evas_Object* obj, void* eventInfo); + virtual void didLoadProgress(Evas_Object* obj, void* eventInfo); + virtual void didLoadProgressFinished(Evas_Object* obj); + virtual void didProcessCrashed(Evas_Object* obj); + virtual void didCreateWindow(Evas_Object* obj, void* eventInfo); + virtual void didCloseWindow(Evas_Object* obj); + virtual void didPolicyNavigationDecide(Evas_Object* obj, void* eventInfo); + virtual void didPolicyNewWindowDecide(Evas_Object* obj, void* eventInfo); + virtual void didPageResponseDecide(Evas_Object* obj); + virtual void didContextmenuCustomize(Evas_Object* obj, void* eventInfo); + virtual void didFormSubmit(Evas_Object* obj); + virtual void didGeolocationPermissionRequest(Evas_Object* obj, void* eventInfo); + virtual void didNotificationShow(Evas_Object* obj, void* eventInfo); + virtual void didNotificationCancel(Evas_Object* obj, void* eventInfo); + virtual void didNotificationPermissionRequest(Evas_Object* obj, void* eventInfo); + virtual void didDatabaseUsagePermissionRequest(Evas_Object* obj, void* eventInfo); + virtual void didFilesystemPermissionRequest(Evas_Object* obj, void* eventInfo); + virtual void didEnterFullscreen(Evas_Object* obj); + virtual void didExitFullscreen(Evas_Object* obj); + virtual void didImeChanged(Evas_Object* obj, void* eventInfo); + virtual void didImeOpened(Evas_Object* obj); + virtual void didImeClosed(Evas_Object* obj); + virtual void didUsermediaPermissionRequest(Evas_Object* obj, void* eventInfo); + virtual void didProtocolHandlerRegistration(Evas_Object* obj, void* eventInfo); + virtual void didProtocolHandlerIsRegistered(Evas_Object* obj, void* eventInfo); + virtual void didProtocolHandlerUnregistration(Evas_Object* obj, void* eventInfo); + virtual void didContentHandlerRegistration(Evas_Object* obj, void* eventInfo); + virtual void didContentHandlerIsRegistered(Evas_Object* obj, void* eventInfo); + virtual void didContentHandlerUnregistration(Evas_Object* obj, void* eventInfo); + virtual void didCertificateConfirmRequest(Evas_Object* obj, void* eventInfo); + + // orientation lock + static Eina_Bool orientationLockCallback( + Evas_Object* obj, Eina_Bool needLock, int orientation, void* data); + static void executeScriptCallback(Evas_Object* obj, const char* result, void* data); + + static std::map<const std::string, const Evas_Smart_Cb> m_smartCallbacksMap; + + // members + Evas_Object* m_topWebview; + std::string m_startUrl; + Evas_Object* m_win; + Ewk_Context* m_ewkContext; +}; + +#endif // WEB_VIEW_H diff --git a/src_mobile/Core/View/injection.js b/src_mobile/Core/View/injection.js new file mode 100644 index 0000000..6616aea --- /dev/null +++ b/src_mobile/Core/View/injection.js @@ -0,0 +1,129 @@ +// set javascript objects for Web APIs of Tizen appwidget +var appTizenObject = 0; +if (typeof window.tizen == 'undefined') { + window.tizen = new Object(); + window.tizen.appwidget = new Object(); +} else { + appTizenObject = 1; +} + +// For future, only window.appwidget will be used +window.appwidget = new Object(); + + +window.appwidget.fireReadyEvent = function () { + // If every functionalities of appwidget are initialized, fire appwidget ready event + var readyevent = document.createEvent("CustomEvent"); + readyevent.initCustomEvent("appwidgetready", true, true); + document.dispatchEvent(readyevent); +}; + +// these are functions for overriding standard javascript functions regarding event +var original_addEventListener = window.addEventListener; +var original_removeEventListener = window.removeEventListener; + +// this variable is responsible to keep information of appwidget evetns +var appWidgetEvents = {}; + +// define event structure for appwidget +window.AppWidgetEventInfo = function(event, callback) { + this.event = event; + this.callback = callback; +}; + +window.addEventListener = function(event, callback, capture) { + var e = event.toLowerCase(); + if (typeof appWidgetEvents[e] != 'undefined') { + appWidgetEvents[e].callback = callback; + } else { + original_addEventListener.call(window, event, callback, capture); + } + + if (e == 'appwidgetready') { + // fire ready event to content + setTimeout(window.appwidget.fireReadyEvent(), 0); + } +}; + +window.removeEventListener = function(event, callback, capture) { + var e = event.toLowerCase(); + if (typeof appWidgetEvents[e] != "undefined") { + appWidgetEvents[e].callback = "null"; + } else { + original_removeEventListener.call(window, event, callback, capture); + } +}; + +window.appwidget.reload = function() { + window.location.href = "box://reload"; +}; + +window.appwidget.changePeriod = function(period) { + switch (arguments.length) { + case 0: + window.location.href = "box://change-period"; + break; + case 1: + window.location.href = "box://change-period?period=" + period; + break; + default: + window.location.href = "box://change-period"; + break; + } +}; + +window.appwidget.launchBrowser = function(url) { + window.location.href = "box://launch-browser?url=" + url; +}; + +window.appwidget.scrollStart = function() { + window.location.href = "box://scroll-start"; +}; + +window.appwidget.scrollStop = function() { + window.location.href = "box://scroll-stop"; +}; + +window.appwidget.sendMessageToBox = function(message) { + window.location.href = "box://send-message-to-box?message=" + message; +}; + +window.appwidget.sendMessageToPd = function(message) { + window.location.href = "box://send-message-to-pd?message=" + message; +}; + +var webprovider = { + // define specific function for registering appwidget event + registerAppWidgetEvent: function(event) { + return (appWidgetEvents[event] = new AppWidgetEventInfo(event, "null")); + }, + + // define specific function for firing registered appwidget event + fireAppWidgetEvent: function(event, data) { + // this is called by web-provider, which is native code + if (typeof appWidgetEvents[event] != 'undefined') { + setTimeout(function() { + appWidgetEvents[event].callback(data); + }, 0); + console.log("fire appwidget event: " + event); + } else { + console.log("unknown appwidget event: " + event); + } + }, +}; + +// register custom events for appwidget +webprovider.registerAppWidgetEvent("pdmessage"); +webprovider.registerAppWidgetEvent("boxmessage"); + +// These objects will be deprecated soon +if (!appTizenObject) { + window.tizen.appwidget.reload = window.appwidget.reload; + window.tizen.appwidget.changePeriod = window.appwidget.changePeriod; + window.tizen.appwidget.launchBrowser = window.appwidget.launchBrowser; + window.tizen.appwidget.scrollStart = window.appwidget.scrollStart; + window.tizen.appwidget.scrollStop = window.appwidget.scrollStop; +} + +// fire ready event explicitly +window.appwidget.fireReadyEvent(); diff --git a/src_mobile/Daemon/BoxDaemon.cpp b/src_mobile/Daemon/BoxDaemon.cpp new file mode 100644 index 0000000..d58153b --- /dev/null +++ b/src_mobile/Daemon/BoxDaemon.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file BoxDaemon.cpp + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#include <string> +#include <app.h> +#include "BoxDaemon.h" +#include "BoxDaemonImpl.h" + +BoxDaemon::BoxDaemon() + : m_impl(new BoxDaemonImpl()) +{ +} + +BoxDaemon::~BoxDaemon() +{ +} + +bool BoxDaemon::start(std::string& name) +{ + return m_impl->start(name); +} + +bool BoxDaemon::stop() +{ + return m_impl->stop(); +} + +bool BoxDaemon::handleAppService(service_h service) +{ + return m_impl->handleAppService(service); +} diff --git a/src_mobile/Daemon/BoxDaemon.h b/src_mobile/Daemon/BoxDaemon.h new file mode 100644 index 0000000..f1bde75 --- /dev/null +++ b/src_mobile/Daemon/BoxDaemon.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file BoxDaemon.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef BOX_DAEMON_H +#define BOX_DAEMON_H + +#include <string> +#include <memory> +#include <app.h> +#include <Core/Util/Noncopyable.h> + +class BoxDaemonImpl; + +class BoxDaemon: Noncopyable { + public: + bool start(std::string& name); + bool stop(); + bool handleAppService(service_h service); + + explicit BoxDaemon(); + ~BoxDaemon(); + + private: + std::shared_ptr<BoxDaemonImpl> m_impl; +}; + +#endif //BOX_DAEMON_H diff --git a/src_mobile/Daemon/BoxDaemonImpl.cpp b/src_mobile/Daemon/BoxDaemonImpl.cpp new file mode 100755 index 0000000..3ff24ba --- /dev/null +++ b/src_mobile/Daemon/BoxDaemonImpl.cpp @@ -0,0 +1,754 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file BoxDaemonImpl.cpp + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#include <API/web_provider_livebox_info.h> +#include <app.h> +#include <appcore-efl.h> +#include <aul.h> +#include <Core/Util/Log.h> +#include <Core/Util/Util.h> +#include <cstring> +#include <Ecore_X.h> +#include <Elementary.h> +#include <livebox-service.h> +#include <Plugin/IBoxPluginConnector.h> +#include <Plugin/BoxPluginConnector.h> +#include <provider.h> +#include <sys/types.h> +#include <string> +#include <unistd.h> +#include <vconf.h> + +#include "BoxDaemonUtil.h" +#include "BoxDaemonImpl.h" + +#define MASTER_PROVIDER_PING_TIME 120.0f + +// These are string for handling application service from app +static const std::string BOX_SERVICE_SCHEME("box-service://"); +static const std::string OPERATION_UPDATE_BOX( + "http://tizen.org/appcontrol/operation/dynamicbox/web/update"); +static const std::string CONTENT_INFO_KEY("content-info"); +static const std::string ALARM_CALLER_KEY("__ALARM_MGR_CALLER_APPID"); + +BoxDaemonImpl::BoxDaemonImpl() + : m_pluginConnector(BoxPluginConnector::create()) +{ + appcore_set_event_callback(APPCORE_EVENT_LANG_CHANGE, requestChangeLanguageCallback, this); + appcore_set_event_callback(APPCORE_EVENT_LOW_MEMORY, requestLowMemoryCallback, this); + appcore_set_event_callback(APPCORE_EVENT_REGION_CHANGE, requestChangeRegionCallback, this); + // reserved + appcore_set_event_callback(APPCORE_EVENT_LOW_BATTERY, NULL, NULL); + + if (vconf_notify_key_changed("db/setting/accessibility/font_name", requestChangeFontCallback, this) != true) { + LogD("vconf_notify_key_changed returned FALSE!"); + } + if (vconf_notify_key_changed(VCONFKEY_SYSTEM_TIME_CHANGED, requestChangeTimeCallback, this) != true) { + LogD("vconf_notify_key_changed returned FALSE!"); + } +} + +BoxDaemonImpl::~BoxDaemonImpl() +{ +} + +bool BoxDaemonImpl::start(std::string& name) +{ + LogD("enter"); + + // initialize existing plugins for web livebox + if (!m_pluginConnector->initialize()) { + LogD("failed to initialize plugins"); + return false; + } + + // set name + m_daemonName = name; + + // provider init + ProviderCallbacks callbacks; + setProviderCallbacks(callbacks); + + int ret = provider_init(ecore_x_display_get(), + m_daemonName.c_str(), + &callbacks, + this); + if (ret < 0) { + LogD("failed to initialize provider"); + return false; + } + + return true; +} + +bool BoxDaemonImpl::stop() +{ + LogD("enter"); + + // deinitialize provider + provider_fini(); + + // deinitialize existing plugins for web livebox + if (!m_pluginConnector->shutdown()) { + LogD("failed to shutdown plugins"); + return false; + } + + return true; +} + +bool BoxDaemonImpl::handleAppService(service_h service) +{ + LogD("enter"); + bool result = false; + char* operation; + + if (service_get_operation(service, &operation) != SERVICE_ERROR_NONE) { + LogD("no operation"); + return false; + } + + if (OPERATION_UPDATE_BOX == operation) { + BoxInfoPtr info = handleOperationUpdate(service); + if (info) { + JobInfo* jobInfo = new JobInfo(REQUEST_CMD_UPDATE_BOX, info, this); + if (ecore_job_add(requestBoxJobCallback, jobInfo)) { + result = true; + } + } + } else { + LogD("unknown operation: %s", operation); + } + + delete[] operation; + return result; +} + +int BoxDaemonImpl::connectedCallback(ProviderEventArgPtr arg, void* data) +{ + LogD("enter"); + UNUSED_PARAM(arg); + + BoxDaemonImpl* This = static_cast<BoxDaemonImpl*>(data); + if (!provider_send_hello()) { + This->m_pingTimer = + ecore_timer_add(MASTER_PROVIDER_PING_TIME, pingToMasterCallback, This); + } + + return 0; +} + +int BoxDaemonImpl::disconnectedCallback(ProviderEventArgPtr arg, void* data) +{ + LogD("enter"); + UNUSED_PARAM(arg); + UNUSED_PARAM(data); + + return 0; +} + +int BoxDaemonImpl::boxCreateCallback( + ProviderEventArgPtr arg, + int* width, int* height, + double* priority, void* data) +{ + LogD("enter"); + UNUSED_PARAM(priority); + + BoxDaemonImpl* This = static_cast<BoxDaemonImpl*>(data); + BoxInfoPtr info = This->initializeBoxInfo(arg); + if (!info) { + return -1; + } + + if ((arg->info.lb_create.width == 0) || (arg->info.lb_create.height == 0)) { + livebox_service_get_size(LB_SIZE_TYPE_1x1, width, height); + } else { + *width = arg->info.lb_create.width; + *height = arg->info.lb_create.height; + } + + info->boxWidth = *width; + info->boxHeight = *height; + info->priority = 1.0f; + info->period = arg->info.lb_create.period; + if (arg->info.lb_create.content) { + info->contentInfo = std::string(arg->info.lb_create.content); + } + + // box information + LogD("--------------------------------------------"); + LogD("boxId: %s", info->boxId.c_str()); + LogD("InstanceId: %s", info->instanceId.c_str()); + LogD("width: %d", info->boxWidth); + LogD("height: %d", info->boxHeight); + LogD("update period: %f", info->period); + LogD("--------------------------------------------"); + + JobInfo* jobInfo = new JobInfo(REQUEST_CMD_ADD_BOX, info, This); + Ecore_Job* ret = ecore_job_add(requestBoxJobCallback, jobInfo); + + return ret ? 0 : -1; +} + +int BoxDaemonImpl::boxReCreateCallback(ProviderEventArgPtr arg, void* data) +{ + LogD("enter"); + + BoxDaemonImpl* This = static_cast<BoxDaemonImpl*>(data); + BoxInfoPtr info = This->initializeBoxInfo(arg); + if (!info) { + return -1; + } + + if ((arg->info.lb_recreate.width == 0) || (arg->info.lb_recreate.height == 0)) { + livebox_service_get_size(LB_SIZE_TYPE_1x1, + &arg->info.lb_recreate.width, + &arg->info.lb_recreate.height); + } + + info->boxWidth = arg->info.lb_recreate.width; + info->boxHeight = arg->info.lb_recreate.height; + info->priority = 1.0f; + info->period = arg->info.lb_recreate.period; + if (arg->info.lb_recreate.content) { + info->contentInfo = std::string(arg->info.lb_recreate.content); + } + + // box information + LogD("--------------------------------------------"); + LogD("boxId: %s", info->boxId.c_str()); + LogD("InstanceId: %s", info->instanceId.c_str()); + LogD("width: %d", info->boxWidth); + LogD("height: %d", info->boxHeight); + LogD("update period: %f", info->period); + LogD("--------------------------------------------"); + + JobInfo* jobInfo = new JobInfo(REQUEST_CMD_ADD_BOX, info, This); + Ecore_Job* ret = ecore_job_add(requestBoxJobCallback, jobInfo); + + return ret ? 0 : -1; +} + +int BoxDaemonImpl::boxDestroyCallback(ProviderEventArgPtr arg, void* data) +{ + LogD("enter"); + + BoxDaemonImpl* This = static_cast<BoxDaemonImpl*>(data); + BoxInfoPtr info = This->initializeBoxInfo(arg); + if (!info) { + return -1; + } + + LogD("--------------------------------------------"); + LogD("boxId: %s", info->boxId.c_str()); + LogD("InstanceId: %s", info->instanceId.c_str()); + LogD("--------------------------------------------"); + + This->m_pluginConnector->requestCommand(REQUEST_CMD_REMOVE_BOX, info); + + return 0; +} + +int BoxDaemonImpl::pdCreateCallback(ProviderEventArgPtr arg, void* data) +{ + LogD("enter"); + + BoxDaemonImpl* This = static_cast<BoxDaemonImpl*>(data); + BoxInfoPtr info = This->initializeBoxInfo(arg); + if (!info) { + return -1; + } + if (arg->info.pd_create.w == 0 || arg->info.pd_create.h == 0) { + return -1; + } + + //Use the screen width to fix the device width + ecore_x_window_size_get(0, &info->pdWidth, NULL); + info->pdHeight = arg->info.pd_create.h; + info->pdX = arg->info.pd_create.x; + info->pdY = arg->info.pd_create.y; + + LogD("--------------------------------------------"); + LogD("boxId: %s", info->boxId.c_str()); + LogD("InstanceId: %s", info->instanceId.c_str()); + LogD("width: %d", info->pdWidth); + LogD("height: %d", info->pdHeight); + LogD("x: %f", info->pdX); + LogD("y: %f", info->pdY); + LogD("--------------------------------------------"); + + JobInfo* jobInfo = new JobInfo(REQUEST_CMD_OPEN_PD, info, This); + Ecore_Job* ret = ecore_job_add(requestBoxJobCallback, jobInfo); + + return ret ? 0 : -1; +} + +int BoxDaemonImpl::pdDestroyCallback(ProviderEventArgPtr arg, void* data) +{ + LogD("enter"); + + BoxDaemonImpl* This = static_cast<BoxDaemonImpl*>(data); + BoxInfoPtr info = This->initializeBoxInfo(arg); + if (!info) { + return -1; + } + + LogD("--------------------------------------------"); + LogD("boxId: %s", info->boxId.c_str()); + LogD("InstanceId: %s", info->instanceId.c_str()); + LogD("--------------------------------------------"); + + JobInfo* jobInfo = new JobInfo(REQUEST_CMD_CLOSE_PD, info, This); + Ecore_Job* ret = ecore_job_add(requestBoxJobCallback, jobInfo); + + return ret ? 0 : -1; +} + +int BoxDaemonImpl::clickedCallback(ProviderEventArgPtr arg, void* data) +{ + LogD("enter"); + + BoxDaemonImpl* This = static_cast<BoxDaemonImpl*>(data); + BoxInfoPtr info = This->initializeBoxInfo(arg); + if (!info) { + return -1; + } + + int flag = web_provider_livebox_get_auto_launch(info->boxId.c_str()); + if (!flag) { + return -1; + } + + BoxDaemonUtil::launchApplication(info->boxId, info->instanceId); + return 0; +} + +int BoxDaemonImpl::boxResizeCallback(ProviderEventArgPtr arg, void* data) +{ + LogD("enter"); + + BoxDaemonImpl* This = static_cast<BoxDaemonImpl*>(data); + BoxInfoPtr info = This->initializeBoxInfo(arg); + if (!info) { + return -1; + } + if (arg->info.resize.w == 0 || arg->info.resize.h == 0) { + return -1; + } + + info->boxWidth = arg->info.resize.w; + info->boxHeight = arg->info.resize.h; + + // box information + LogD("--------------------------------------------"); + LogD("boxId: %s", info->boxId.c_str()); + LogD("InstanceId: %s", info->instanceId.c_str()); + LogD("width: %d", info->boxWidth); + LogD("height: %d", info->boxHeight); + LogD("--------------------------------------------"); + + JobInfo* jobInfo = new JobInfo(REQUEST_CMD_RESIZE_BOX, info, This); + Ecore_Job* ret = ecore_job_add(requestBoxJobCallback, jobInfo); + + return ret ? 0 : -1; +} + +int BoxDaemonImpl::boxPauseCallback(ProviderEventArgPtr arg, void* data) +{ + LogD("enter"); + + BoxDaemonImpl* This = static_cast<BoxDaemonImpl*>(data); + BoxInfoPtr info = This->initializeBoxInfo(arg); + if (!info) { + return -1; + } + + // box information + LogD("--------------------------------------------"); + LogD("boxId: %s", info->boxId.c_str()); + LogD("InstanceId: %s", info->instanceId.c_str()); + LogD("--------------------------------------------"); + + JobInfo* jobInfo = new JobInfo(REQUEST_CMD_PAUSE_BOX, info, This); + Ecore_Job* ret = ecore_job_add(requestBoxJobCallback, jobInfo); + + return ret ? 0 : -1; +} + +int BoxDaemonImpl::boxResumeCallback(ProviderEventArgPtr arg, void* data) +{ + LogD("enter"); + + BoxDaemonImpl* This = static_cast<BoxDaemonImpl*>(data); + BoxInfoPtr info = This->initializeBoxInfo(arg); + if (!info) { + return -1; + } + + // box information + LogD("--------------------------------------------"); + LogD("boxId: %s", info->boxId.c_str()); + LogD("InstanceId: %s", info->instanceId.c_str()); + LogD("--------------------------------------------"); + + JobInfo* jobInfo = new JobInfo(REQUEST_CMD_RESUME_BOX, info, This); + Ecore_Job* ret = ecore_job_add(requestBoxJobCallback, jobInfo); + + return ret ? 0 : -1; +} + +int BoxDaemonImpl::pauseCallback(ProviderEventArgPtr arg, void* data) +{ + LogD("enter"); + UNUSED_PARAM(arg); + + BoxDaemonImpl* This = static_cast<BoxDaemonImpl*>(data); + + LogD("--------------------------------------------"); + LogD("web-provider is paused"); + LogD("--------------------------------------------"); + + JobInfo* jobInfo = new JobInfo(REQUEST_CMD_PAUSE_ALL, BoxInfoPtr(), This); + Ecore_Job* ret = ecore_job_add(requestBoxJobCallback, jobInfo); + + return ret ? 0 : -1; +} + +int BoxDaemonImpl::resumeCallback(ProviderEventArgPtr arg, void* data) +{ + LogD("enter"); + UNUSED_PARAM(arg); + + BoxDaemonImpl* This = static_cast<BoxDaemonImpl*>(data); + + LogD("--------------------------------------------"); + LogD("web-provider is resumed"); + LogD("--------------------------------------------"); + + JobInfo* jobInfo = new JobInfo(REQUEST_CMD_RESUME_ALL, BoxInfoPtr(), This); + Ecore_Job* ret = ecore_job_add(requestBoxJobCallback, jobInfo); + + return ret ? 0 : -1; +} + +int BoxDaemonImpl::boxPeriodChangeCallback(ProviderEventArgPtr arg, void* data) +{ + LogD("enter"); + BoxDaemonImpl* This = static_cast<BoxDaemonImpl*>(data); + BoxInfoPtr info = This->initializeBoxInfo(arg); + if (!info) { + return -1; + } + info->period = arg->info.set_period.period; + + LogD("--------------------------------------------"); + LogD("boxId: %s", info->boxId.c_str()); + LogD("InstanceId: %s", info->instanceId.c_str()); + LogD("period: %f", info->period); + LogD("--------------------------------------------"); + + JobInfo* jobInfo = new JobInfo(REQUEST_CMD_CHANGE_PERIOD, info, This); + Ecore_Job* ret = ecore_job_add(requestBoxJobCallback, jobInfo); + + return ret ? 0 : -1; +} + +int BoxDaemonImpl::boxUpdateCallback(ProviderEventArgPtr arg, void* data) +{ + LogD("enter"); + + BoxDaemonImpl* This = static_cast<BoxDaemonImpl*>(data); + BoxInfoPtr info = This->initializeBoxInfo(arg); + if (!info) { + return -1; + } + + LogD("--------------------------------------------"); + LogD("boxId: %s", info->boxId.c_str()); + LogD("InstanceId: %s", info->instanceId.c_str()); + LogD("--------------------------------------------"); + + JobInfo* jobInfo = new JobInfo(REQUEST_CMD_UPDATE_BOX, info, This); + Ecore_Job* ret = ecore_job_add(requestBoxJobCallback, jobInfo); + + return ret ? 0 : -1; +} + +void BoxDaemonImpl::setProviderCallbacks(ProviderCallbacks& callbacks) +{ + LogD("enter"); + + memset(&callbacks, 0, sizeof(callbacks)); + callbacks.connected = BoxDaemonImpl::connectedCallback; + callbacks.disconnected = BoxDaemonImpl::disconnectedCallback; + callbacks.pause = BoxDaemonImpl::pauseCallback; + callbacks.resume = BoxDaemonImpl::resumeCallback; + callbacks.lb_create = BoxDaemonImpl::boxCreateCallback; + callbacks.lb_recreate = BoxDaemonImpl::boxReCreateCallback; + callbacks.lb_destroy = BoxDaemonImpl::boxDestroyCallback; + callbacks.lb_pause = BoxDaemonImpl::boxPauseCallback; + callbacks.lb_resume = BoxDaemonImpl::boxResumeCallback; + callbacks.pd_create = BoxDaemonImpl::pdCreateCallback; + callbacks.pd_destroy = BoxDaemonImpl::pdDestroyCallback; + callbacks.clicked = BoxDaemonImpl::clickedCallback; + callbacks.resize = BoxDaemonImpl::boxResizeCallback; + callbacks.update_content = BoxDaemonImpl::boxUpdateCallback; + callbacks.set_period = BoxDaemonImpl::boxPeriodChangeCallback; +} + +std::string BoxDaemonImpl::getBoxType(const char* boxId) +{ + LogD("enter"); + + if (!boxId) { + return std::string(); + } + + const char* type = web_provider_livebox_get_box_type(boxId); + if (!type) { + std::string boxType = m_pluginConnector->getBoxType(boxId); + if (boxType.empty()) { + LogD("unrecognized box id"); + } else { + LogD("box id: %s, type: %s", boxId, boxType.c_str()); + } + return boxType; + } + + LogD("box id: %s, type: %s", boxId, type); + std::string result{type}; + free(const_cast<char*>(type)); + return result; +} + +BoxInfoPtr BoxDaemonImpl::initializeBoxInfo(ProviderEventArgPtr arg) +{ + LogD("enter"); + + if (!arg) { + return BoxInfoPtr(); + } + + if (!arg->pkgname || !arg->id) { + LogD("pkgname or id don't exist"); + return BoxInfoPtr(); + } + + std::string type = getBoxType(arg->pkgname); + if (type.empty()) { + return BoxInfoPtr(); + } + BoxInfoPtr infoPtr = BoxInfoPtr(new BoxInfo(type, arg->pkgname, arg->id)); + + return infoPtr; +} + +std::string BoxDaemonImpl::getBoxIdFromService(service_h service) +{ + LogD("enter"); + + int ret; + char* serviceUri = NULL; + ret = service_get_uri(service, &serviceUri); + if (ret != SERVICE_ERROR_NONE) { + LogD("no box uri"); + return std::string(); + } + + std::string uri(serviceUri); + delete[] serviceUri; + + if(uri.compare(0, BOX_SERVICE_SCHEME.size(), BOX_SERVICE_SCHEME)) { + // uri is not box-service scheme + return std::string(); + } + + std::string boxId = uri.substr(BOX_SERVICE_SCHEME.size()); + return boxId; +} + +bool BoxDaemonImpl::isServiceCallerBoxOwner(service_h service) +{ + LogD("enter"); + + int ret; + + std::string boxId = getBoxIdFromService(service); + if (boxId.empty()) { + LogD("error box-id"); + return false; + } + + // check if caller is owner of this box + const char* appId = web_provider_livebox_get_app_id(boxId.c_str()); + if (!appId) { + return false; + } + std::string ownerAppId(appId); + delete[] appId; + + char* caller = NULL; + ret = service_get_caller(service, &caller); + if (ret != SERVICE_ERROR_NONE) { + ret = service_get_extra_data( + service, ALARM_CALLER_KEY.c_str(), &caller); + if (ret != SERVICE_ERROR_NONE) { + LogD("failed to get caller's appid from service"); + return false; + } + } + std::string callerAppId(caller); + + // release strings + delete[] caller; + + if (ownerAppId != callerAppId) { + LogD("caller is not matched with owner of requested box"); + return false; + } + + return true; +} + +BoxInfoPtr BoxDaemonImpl::handleOperationUpdate(service_h service) +{ + LogD("enter"); + + if (!isServiceCallerBoxOwner(service)) { + return BoxInfoPtr(); + } + + std::string boxId = getBoxIdFromService(service); + if (boxId.empty()) { + LogD("error box-id"); + return BoxInfoPtr(); + } + + char* contentInfo = NULL; + service_get_extra_data(service, CONTENT_INFO_KEY.c_str(), &contentInfo); + + std::string type(getBoxType(boxId.c_str())); + if (type.empty()) { + LogD("no type for this box"); + delete[] contentInfo; + return BoxInfoPtr(); + } + BoxInfoPtr info = BoxInfoPtr(new BoxInfo(type, boxId, "")); + if (contentInfo) { + info->contentInfo = std::string(contentInfo); + } + + // release string + delete[] contentInfo; + + return info; +} + +Eina_Bool BoxDaemonImpl::pingToMasterCallback(void* data) +{ + LogD("enter"); + UNUSED_PARAM(data); + + provider_send_ping(); + + return ECORE_CALLBACK_RENEW; +} + +void BoxDaemonImpl::requestBoxJobCallback(void* data) +{ + JobInfo* jobInfo = static_cast<JobInfo*>(data); + if (!jobInfo) { + LogD("no information for job"); + return; + } + + // just for debugging + //volatile int flag = 0; + //while(flag == 0) {;} + + // request box job! + jobInfo->daemonImpl->m_pluginConnector->requestCommand( + jobInfo->cmdType, jobInfo->boxInfo); + + delete jobInfo; +} + +int BoxDaemonImpl::requestChangeLanguageCallback(void* data) +{ + LogD("enter"); + + BoxDaemonImpl* This = static_cast<BoxDaemonImpl*>(data); + BoxInfoPtr info = BoxInfoPtr(new BoxInfo()); + JobInfo* jobInfo = new JobInfo(REQUEST_CMD_CHANGE_LANGUAGE, info, This); + + ecore_job_add(requestBoxJobCallback, jobInfo); + return 0; +} + +int BoxDaemonImpl::requestChangeRegionCallback(void* data) +{ + LogD("enter"); + + BoxDaemonImpl* This = static_cast<BoxDaemonImpl*>(data); + BoxInfoPtr info = BoxInfoPtr(new BoxInfo()); + JobInfo* jobInfo = new JobInfo(REQUEST_CMD_CHANGE_LANGUAGE, info, This); + + ecore_job_add(requestBoxJobCallback, jobInfo); + return 0; +} +int BoxDaemonImpl::requestLowMemoryCallback(void* data) +{ + LogD("enter"); + UNUSED_PARAM(data); + + // terminate box daemon and revive + elm_exit(); + return 0; +} + +void BoxDaemonImpl::requestChangeFontCallback(keynode_t* key, void* data) +{ + LogD("enter"); + UNUSED_PARAM(key); + + char* fontstr = vconf_get_str("db/setting/accessibility/font_name"); + + BoxDaemonImpl* This = static_cast<BoxDaemonImpl*>(data); + BoxInfoPtr info = BoxInfoPtr(new BoxInfo()); + JobInfo* jobInfo = new JobInfo(REQUEST_CMD_CHANGE_LANGUAGE, info, This); + + free(fontstr); + ecore_job_add(requestBoxJobCallback, jobInfo); +} + +void BoxDaemonImpl::requestChangeTimeCallback(keynode_t* key, void* data) +{ + LogD("enter"); + UNUSED_PARAM(key); + + char* timestr = vconf_get_str(VCONFKEY_SYSTEM_TIME_CHANGED); + + BoxDaemonImpl* This = static_cast<BoxDaemonImpl*>(data); + BoxInfoPtr info = BoxInfoPtr(new BoxInfo()); + JobInfo* jobInfo = new JobInfo(REQUEST_CMD_CHANGE_LANGUAGE, info, This); + + free(timestr); + ecore_job_add(requestBoxJobCallback, jobInfo); +} diff --git a/src_mobile/Daemon/BoxDaemonImpl.h b/src_mobile/Daemon/BoxDaemonImpl.h new file mode 100644 index 0000000..9ee5e10 --- /dev/null +++ b/src_mobile/Daemon/BoxDaemonImpl.h @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file BoxDaemonImpl.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef BOX_DAEMON_IMPL_H +#define BOX_DAEMON_IMPL_H + +#include <string> +#include <memory> +#include <app.h> +#include <provider.h> +#include <Eina.h> +#include <Ecore.h> +#include <Plugin/box_plugin_interface.h> +#include <Core/BoxData.h> +#include <vconf.h> + +// forward declaration +class IBoxManager; +class IBoxPluginConnector; + +class BoxDaemonImpl { + public: + bool start(std::string& name); + bool stop(); + bool handleAppService(service_h service); + + public: + explicit BoxDaemonImpl(); + ~BoxDaemonImpl(); + + private: + // type definition + typedef struct event_arg ProviderEventArg; + typedef ProviderEventArg* ProviderEventArgPtr; + typedef struct event_handler ProviderCallbacks; + typedef ProviderCallbacks* ProviderCallbacksPtr; + + // livebox's provider callbacks + static int connectedCallback(ProviderEventArgPtr arg, void* data); + static int disconnectedCallback(ProviderEventArgPtr arg, void* data); + static int boxCreateCallback( + ProviderEventArgPtr arg, + int* width, int* height, + double* priority, void* data); + static int boxReCreateCallback(ProviderEventArgPtr arg, void* data); + static int boxDestroyCallback(ProviderEventArgPtr arg, void* data); + static int pdCreateCallback(ProviderEventArgPtr arg, void* data); + static int pdDestroyCallback(ProviderEventArgPtr arg, void* data); + static int clickedCallback(ProviderEventArgPtr arg, void* data); + static int boxResizeCallback(ProviderEventArgPtr arg, void* data); + static int boxPauseCallback(ProviderEventArgPtr arg, void* data); + static int boxResumeCallback(ProviderEventArgPtr arg, void* data); + static int pauseCallback(ProviderEventArgPtr arg, void* data); + static int resumeCallback(ProviderEventArgPtr arg, void* data); + static int boxPeriodChangeCallback(ProviderEventArgPtr arg, void* data); + static int boxUpdateCallback(ProviderEventArgPtr arg, void* data); + // callback for app-core event + static int requestChangeLanguageCallback(void* data); + static int requestChangeRegionCallback(void* data); + static int requestLowMemoryCallback(void* data); + // callback for vconf event + static void requestChangeFontCallback(keynode_t* key, void* data); + static void requestChangeTimeCallback(keynode_t* key, void* data); + // common private functions + void setProviderCallbacks(ProviderCallbacks& callbacks); + std::string getBoxType(const char* boxId); + BoxInfoPtr initializeBoxInfo(ProviderEventArgPtr arg); + + // functions for handling appcontrol per operation + std::string getBoxIdFromService(service_h service); + bool isServiceCallerBoxOwner(service_h service); + BoxInfoPtr handleOperationUpdate(service_h service); + + // callback for ping to master daemon + static Eina_Bool pingToMasterCallback(void* data); + + // callback for requested jobs of boxes + static void requestBoxJobCallback(void* data); + + // members + std::string m_daemonName; + Ecore_Timer* m_pingTimer; + std::shared_ptr<IBoxPluginConnector> m_pluginConnector; +}; + +struct JobInfo { + request_cmd_type cmdType; + BoxInfoPtr boxInfo; + BoxDaemonImpl* daemonImpl; + + JobInfo(request_cmd_type cmdType, + BoxInfoPtr boxInfo, + BoxDaemonImpl* daemonImpl) : + cmdType(cmdType), + boxInfo(boxInfo), + daemonImpl(daemonImpl) + { + }; +}; + + +#endif //BOX_DAEMON_IMPL_H + diff --git a/src_mobile/Daemon/BoxDaemonUtil.cpp b/src_mobile/Daemon/BoxDaemonUtil.cpp new file mode 100644 index 0000000..00668a3 --- /dev/null +++ b/src_mobile/Daemon/BoxDaemonUtil.cpp @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file BoxDaemonUtil.cpp + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#include <string> +#include <memory> +#include <app_service.h> +#include <Core/Util/Log.h> +#include <API/web_provider_livebox_info.h> +#include "BoxDaemonUtil.h" + +const std::string BoxDaemonUtil::boxIdKey("box-id"); +const std::string BoxDaemonUtil::instanceIdKey("instance-id"); + +bool BoxDaemonUtil::launchApplication(std::string& boxId, std::string& instanceId) +{ + LogD("enter"); + + std::shared_ptr<const char> appId(web_provider_livebox_get_app_id(boxId.c_str())); + if (!appId) { + LogD("no appid of %s", boxId.c_str()); + return false; + } + + service_h handle = NULL; + int ret = SERVICE_ERROR_NONE; + + ret = service_create(&handle); + if (ret != SERVICE_ERROR_NONE && !handle) { + LogD("failed to create service"); + return false; + } + + ret = service_set_package(handle, appId.get()); + if (ret != SERVICE_ERROR_NONE) { + LogD("failed to set package"); + service_destroy(handle); + return false; + } + + service_add_extra_data(handle, boxIdKey.c_str(), boxId.c_str()); + service_add_extra_data(handle, instanceIdKey.c_str(), instanceId.c_str()); + + ret = service_send_launch_request(handle, NULL, NULL); + if (ret != SERVICE_ERROR_NONE) { + LogD("failed to launch package"); + service_destroy(handle); + return false; + } + + service_destroy(handle); + LogD("success to launch app of %s", boxId.c_str()); + + return true; +} diff --git a/src_mobile/Daemon/BoxDaemonUtil.h b/src_mobile/Daemon/BoxDaemonUtil.h new file mode 100644 index 0000000..0f0406f --- /dev/null +++ b/src_mobile/Daemon/BoxDaemonUtil.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file BoxDaemonUtil.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef BOX_DAEMON_UTIL_H +#define BOX_DAEMON_UTIL_H + +#include <string> + +class BoxDaemonUtil { + public: + static bool launchApplication(std::string& boxId, std::string& instanceId); + + private: + static const std::string boxIdKey; + static const std::string instanceIdKey; + +}; + +#endif // BOX_DAEMON_UTIL_H diff --git a/src_mobile/Daemon/CMakeLists.txt b/src_mobile/Daemon/CMakeLists.txt new file mode 100644 index 0000000..589c422 --- /dev/null +++ b/src_mobile/Daemon/CMakeLists.txt @@ -0,0 +1,66 @@ +# Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved +# +# Licensed under the Flora License, Version 1.1 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://floralicense.org/license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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) + +SET(TARGET_NAME ${TARGET_DAEMON}) +SET(DEPS ${TARGET_NAME}_DEPS) + +PKG_CHECK_MODULES(${DEPS} + aul + bundle + appcore-efl + elementary + ecore-x + provider + livebox-service + capi-appfw-application + dlog + REQUIRED +) +ADD_DEFINITIONS(${${DEPS}_CFLAGS}) + +SET(SRCS + ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/BoxDaemon.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/BoxDaemonImpl.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/BoxDaemonUtil.cpp +) + +SET(HEADERS + ${${DEPS}_INCLUDE_DIRS} + ${CMAKE_CURRENT_SOURCE_DIR} +) +INCLUDE_DIRECTORIES(${HEADERS}) + +ADD_EXECUTABLE(${TARGET_NAME} ${SRCS}) + +SET_TARGET_PROPERTIES(${TARGET_NAME} PROPERTIES + COMPILE_FLAGS -fPIC + LINK_FLAGS "-Wl,--as-needed -Wl,--hash-style=both" +) + +TARGET_LINK_LIBRARIES(${TARGET_NAME} + ${${DEPS}_LDFLAGS} "-ldl -lcap" + ${${DEPS}_LIBRARIES} + ${TARGET_PLUGIN} + ${TARGET_CORE} + ${TARGET_API} +) + +INSTALL(TARGETS ${TARGET_NAME} + DESTINATION /usr/apps/livebox.${PROJECT_NAME}/bin + PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE + GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE +) diff --git a/src_mobile/Daemon/main.cpp b/src_mobile/Daemon/main.cpp new file mode 100755 index 0000000..1b8863d --- /dev/null +++ b/src_mobile/Daemon/main.cpp @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file main.cpp + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ + +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/capability.h> +#include <Elementary.h> +#include <aul.h> +#include <app.h> +#include <Core/Util/Log.h> +#include <Core/Util/Util.h> +#include "BoxDaemon.h" + + +// declarations +static BoxDaemon boxDaemon; +static bool isDaemonReleased = false; + +static void atExitCallback() +{ + LogD("enter"); + if (isDaemonReleased) { + return; + } + + // this callback is called due to abnormal exit() + LogD("release daemon resources explicitly"); + boxDaemon.stop(); +} + +static bool appCreateCallback(void *data) +{ + LogD("app create"); + UNUSED_PARAM(data); + + elm_config_preferred_engine_set("software_x11"); + return true; +} + +static void appTerminateCallback(void *data) +{ + BoxDaemon *boxDaemon = static_cast<BoxDaemon *>(data); + boxDaemon->stop(); + isDaemonReleased = true; +} + +static void appPauseCallback(void *data) +{ + LogD("app pasue"); +} + +static void appResumeCallback(void *data) +{ + LogD("app resume"); +} + +static void appServiceCallback(service_h service, void *data) +{ + LogD("app service"); + + int ret; + char* name; + + BoxDaemon *boxDaemon = static_cast<BoxDaemon*>(data); + ret = service_get_extra_data(service, "name", &name); + + // check if web-provider is launched, or not + if (ret == SERVICE_ERROR_NONE) { + std::string daemonName(name); + if(!(boxDaemon->start(daemonName))) { + LogD("daemon failed to start"); + elm_exit(); + } + atexit(atExitCallback); + return; + } + + boxDaemon->handleAppService(service); +} + +static bool grantProcessCapability() +{ + cap_user_header_t header; + cap_user_data_t data; + + header = static_cast<cap_user_header_t>(malloc(sizeof(*header))); + data = static_cast<cap_user_data_t>(calloc(sizeof(*data), _LINUX_CAPABILITY_U32S_3)); + + header->pid = getpid(); + header->version = _LINUX_CAPABILITY_VERSION_3; + + // read already granted capabilities of this process + if (capget(header, data) < 0) { + LogD("capget error"); + free(header); + free(data); + return false; + } + + // set only inheritable bit for CAP_MAC_ADMIN to '1' + data[CAP_TO_INDEX(CAP_MAC_ADMIN)].inheritable |= CAP_TO_MASK(CAP_MAC_ADMIN); + + // remove capabilities not needed any more + data[CAP_TO_INDEX(CAP_MAC_ADMIN)].permitted &= ~CAP_TO_MASK(CAP_MAC_ADMIN); + data[CAP_TO_INDEX(CAP_MAC_ADMIN)].effective &= ~CAP_TO_MASK(CAP_MAC_ADMIN); + data[CAP_TO_INDEX(CAP_SETPCAP)].permitted &= ~CAP_TO_MASK(CAP_SETPCAP); + data[CAP_TO_INDEX(CAP_SETPCAP)].effective &= ~CAP_TO_MASK(CAP_SETPCAP); + + bool ret = true; + if (capset(header, data) < 0) { + LogD("capset error"); + ret = false; + } + + free(header); + free(data); + + return ret; +} + +int main (int argc, char *argv[]) +{ + // set inheritable bit for CAP_MAC_ADMIN + // so that WebProcess will have CAP_MAC_ADMIN capability + if (!grantProcessCapability()) { + return -1; + } + + // set the appcore callbacks + app_event_callback_s ops; + memset(&ops, 0x00, sizeof(app_event_callback_s)); + ops.create = appCreateCallback; + ops.terminate = appTerminateCallback; + ops.pause = appPauseCallback; + ops.resume = appResumeCallback; + ops.service = appServiceCallback; + + // start appcore + int ret = app_efl_main(&argc, &argv, &ops, &boxDaemon); + return ret; +} diff --git a/src_mobile/Plugin/AppBoxPlugin/AppBoxManager.cpp b/src_mobile/Plugin/AppBoxPlugin/AppBoxManager.cpp new file mode 100755 index 0000000..6285b5c --- /dev/null +++ b/src_mobile/Plugin/AppBoxPlugin/AppBoxManager.cpp @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file AppBoxManager.cpp + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#include <map> +#include <ail.h> +#include <ewk_context.h> +#include <core_module.h> +#include <Plugin/IBoxPluginFactory.h> +#include <Core/BoxData.h> +#include <Core/BoxManager.h> +#include <Core/IBox.h> +#include <Core/Util/Log.h> +#include <API/web_provider_livebox_info.h> +#include "AppBoxObserver.h" +#include "AppBoxManager.h" + +static const std::string bundlePath("/usr/lib/libwrt-injected-bundle.so"); + +AppBoxManager::AppBoxManager(IBoxPluginFactoryPtr factory) + : BoxManager(factory) +{ + bool ret = WRT::CoreModuleSingleton::Instance().Init(); + if (!ret) { + throw; // throw exeception + } + AppBoxObserver::Instance()->initialize(); +} + +AppBoxManager::~AppBoxManager() +{ + AppBoxObserver::Instance()->shutdown(); +} + +bool AppBoxManager::requestAddBox(BoxInfoPtr boxInfo, EwkContextPtr ewkContext) +{ + + const char* appId = + web_provider_livebox_get_app_id(boxInfo->boxId.c_str()); + + if (!appId) { + LogD("no appid of %s", boxInfo->boxId.c_str()); + return false; + } + + std::string appIdStr(appId); + delete appId; + + auto it = m_ewkContextMap.find(appIdStr); + if (it == m_ewkContextMap.end()) { + ewkContext = getAvailableEwkContext(appIdStr); + insertContextMap(appIdStr, ewkContext); + } else { + ewkContext = it->second; + } + + if (!BoxManager::requestAddBox(boxInfo, ewkContext)) { + return false; + } + + return true; +} + +bool AppBoxManager::requestRemoveBox(std::string& instanceId) +{ + if (!BoxManager::requestRemoveBox(instanceId)) { + return false; + } + + return true; +} + +EwkContextPtr AppBoxManager::getAvailableEwkContext(const std::string& appId) +{ + + // get the base executable path + std::string baseExecutablePath = getBaseExecutablePath(appId); + if (baseExecutablePath.empty()) { + return EwkContextPtr(); + } + + // get web process path for this box + std::string webProcessPath = baseExecutablePath + ".d-box"; + + // get plugin process path for this box + std::string pluginProcessPath = baseExecutablePath + ".npruntime"; + + // box manager should set webprocess path as value of 'WEB_PROCESS_PATH' + // before calling ewk_context_new_with_injected_bundle_path(). + setenv("WEB_PROCESS_EXECUTABLE_PATH", webProcessPath.c_str(), 1); + setenv("PLUGIN_PROCESS_EXECUTABLE_PATH", pluginProcessPath.c_str(), 1); + + EwkContextPtr newEwkContext( + ewk_context_new_with_injected_bundle_path(bundlePath.c_str()), + BoxManager::EwkContextDeleter()); + + // unset the following env variables not to affect other ewk context creation + unsetenv("WEB_PROCESS_EXECUTABLE_PATH"); + unsetenv("PLUGIN_PROCESS_EXECUTABLE_PATH"); + + return newEwkContext; +} + +void AppBoxManager::insertContextMap(std::string& appId, EwkContextPtr ewkContext) +{ + m_ewkContextMap.insert(EwkContextMapPair(appId, ewkContext)); +} + +void AppBoxManager::eraseContextMap(std::string& appId) +{ + m_ewkContextMap.erase(appId); +} + +std::string AppBoxManager::getBaseExecutablePath(const std::string& appId) +{ + ail_error_e ret; + ail_appinfo_h handle = NULL; + + char* retStr = NULL; + ret = ail_get_appinfo(appId.c_str(), &handle); + if (ret != AIL_ERROR_OK) { + return std::string(); + } + + ret = ail_appinfo_get_str(handle, AIL_PROP_X_SLP_EXE_PATH, &retStr); + if (ret != AIL_ERROR_OK || !retStr) { + return std::string(); + } + + std::string basePath(retStr); + + ret = ail_destroy_appinfo(handle); + if (ret != AIL_ERROR_OK) { + return std::string(); + } + + return basePath; +} diff --git a/src_mobile/Plugin/AppBoxPlugin/AppBoxManager.h b/src_mobile/Plugin/AppBoxPlugin/AppBoxManager.h new file mode 100644 index 0000000..89f942f --- /dev/null +++ b/src_mobile/Plugin/AppBoxPlugin/AppBoxManager.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file AppBoxManager.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef APP_BOX_MANAGER_H +#define APP_BOX_MANAGER_H + +#include <Core/IBox.h> +#include <Core/IBoxManager.h> +#include <Core/BoxManager.h> +#include <Core/BoxData.h> +#include <Plugin/IBoxPluginFactory.h> + +class AppBoxManager: public BoxManager { + public: + static IBoxManagerPtr create(IBoxPluginFactoryPtr factory) + { + return IBoxManagerPtr(new AppBoxManager(factory)); + }; + ~AppBoxManager(); + + private: + // BoxManager implementation + bool requestAddBox(BoxInfoPtr boxInfo, EwkContextPtr ewkContext); + bool requestRemoveBox(std::string& instanceId); + + EwkContextPtr getAvailableEwkContext(const std::string& appId); + void insertContextMap(std::string& appId, EwkContextPtr ewkContext); + void eraseContextMap(std::string& appId); + std::string getBaseExecutablePath(const std::string& appId); + explicit AppBoxManager(IBoxPluginFactoryPtr factory); + + // members + typedef std::map<std::string, EwkContextPtr> EwkContextMap; + typedef std::pair<std::string, EwkContextPtr> EwkContextMapPair; + EwkContextMap m_ewkContextMap; +}; + + +#endif // APP_BOX_MANAGER_H diff --git a/src_mobile/Plugin/AppBoxPlugin/AppBoxObserver.cpp b/src_mobile/Plugin/AppBoxPlugin/AppBoxObserver.cpp new file mode 100644 index 0000000..45514e8 --- /dev/null +++ b/src_mobile/Plugin/AppBoxPlugin/AppBoxObserver.cpp @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file AppBoxObserver.cpp + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ + +#include <string> +#include <map> +#include <Core/Util/Log.h> +#include <Elementary.h> +#include <ewk_view.h> +#include <ewk_context.h> +#include "AppBoxRenderView.h" +#include "AppBoxRenderBuffer.h" +#include "AppBoxObserver.h" + +// static variable intialization +AppBoxObserver* AppBoxObserver::s_instance = NULL; + +static const std::string bundlePath("/usr/lib/libwrt-injected-bundle.so"); + +AppBoxObserver::AppBoxObserver() + : m_initialized(false) + , m_renderViewMap() + , m_renderBufferMap() +{ + LogD("enter"); + Ewk_Context* ctx = ewk_context_new_with_injected_bundle_path(bundlePath.c_str()); + m_pdEwkContext.reset(ctx, ewk_context_delete); + // create dummy webview to keep PD's WebProcess alive + //Evas_Object* win = elm_win_add(NULL, "dummy-win", ELM_WIN_BASIC); + //Evas_Object* webview = + // ewk_view_add_with_context(evas_object_evas_get(win), m_pdEwkContext.get()); +} + +AppBoxObserver::~AppBoxObserver() +{ + LogD("enter"); + if (m_pdEwkContext) { + ewk_context_delete(m_pdEwkContext.get()); + } +} + +AppBoxObserver* AppBoxObserver::Instance() +{ + LogD("enter"); + if (!s_instance) { + s_instance = new AppBoxObserver(); + } + + return s_instance; +} + +void AppBoxObserver::initialize() +{ + LogD("enter"); + if (m_initialized) { + LogD("already initialized"); + return; + } + + m_initialized = true; +} + +void AppBoxObserver::shutdown() +{ + LogD("enter"); + if (!m_initialized) { + LogD("not yet initialized"); + return; + } + + m_initialized = false; +} + +AppBoxRenderView* AppBoxObserver::getRenderView(std::string instanceId) +{ + LogD("enter"); + + auto it = m_renderViewMap.find(instanceId); + if (it != m_renderViewMap.end()) { + LogD("registered: %s (%p)", it->first.c_str(), it->second); + return it->second; + } + + return NULL; +} + +std::shared_ptr<Ewk_Context> AppBoxObserver::getPdEwkContext() +{ + LogD("enter"); + return m_pdEwkContext; +} + +void AppBoxObserver::registerRenderView(std::string instanceId, AppBoxRenderView* view) +{ + LogD("enter"); + + if (getRenderView(instanceId)) { + LogD("already registered"); + return; + } + + m_renderViewMap.insert(RenderViewMapPair(instanceId, view)); +} + +void AppBoxObserver::unregisterRenderView(std::string instanceId) +{ + LogD("enter"); + m_renderViewMap.erase(instanceId); +} + +AppBoxRenderBuffer* AppBoxObserver::getRenderBuffer(std::string instanceId) +{ + LogD("enter"); + + auto it = m_renderBufferMap.find(instanceId); + if (it != m_renderBufferMap.end()) { + LogD("registered: %s (%p)", it->first.c_str(), it->second); + return it->second; + } + + return NULL; +} + +void AppBoxObserver::registerRenderBuffer(std::string instanceId, AppBoxRenderBuffer* buffer) +{ + LogD("enter"); + + if (getRenderBuffer(instanceId)) { + LogD("already registered"); + return; + } + + m_renderBufferMap.insert(RenderBufferMapPair(instanceId, buffer)); +} + +void AppBoxObserver::unregisterRenderBuffer(std::string instanceId) +{ + LogD("enter"); + m_renderBufferMap.erase(instanceId); +} diff --git a/src_mobile/Plugin/AppBoxPlugin/AppBoxObserver.h b/src_mobile/Plugin/AppBoxPlugin/AppBoxObserver.h new file mode 100644 index 0000000..8042f33 --- /dev/null +++ b/src_mobile/Plugin/AppBoxPlugin/AppBoxObserver.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file AppBoxObserver.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef APP_BOX_OBSERVER_H +#define APP_BOX_OBSERVER_H + +#include <string> +#include <map> +#include <memory> + +class AppBoxRenderView; +class AppBoxRenderBuffer; + +class AppBoxObserver { + public: + static AppBoxObserver* Instance(); + void initialize(); + void shutdown(); + void registerRenderView(std::string instanceId, AppBoxRenderView* view); + void unregisterRenderView(std::string instanceId); + void registerRenderBuffer(std::string instanceId, AppBoxRenderBuffer* view); + void unregisterRenderBuffer(std::string instanceId); + AppBoxRenderView* getRenderView(std::string instanceId); + AppBoxRenderBuffer* getRenderBuffer(std::string instanceId); + std::shared_ptr<Ewk_Context> getPdEwkContext(); + + private: + AppBoxObserver(); + ~AppBoxObserver(); + + typedef std::map<std::string, AppBoxRenderView*> RenderViewMap; + typedef std::pair<std::string, AppBoxRenderView*> RenderViewMapPair; + typedef std::map<std::string, AppBoxRenderBuffer*> RenderBufferMap; + typedef std::pair<std::string, AppBoxRenderBuffer*> RenderBufferMapPair; + + bool m_initialized; + RenderViewMap m_renderViewMap; + RenderBufferMap m_renderBufferMap; + std::shared_ptr<Ewk_Context> m_pdEwkContext; + static AppBoxObserver* s_instance; +}; + +#endif //APP_BOX_OBSERVER_H diff --git a/src_mobile/Plugin/AppBoxPlugin/AppBoxPdHelper.cpp b/src_mobile/Plugin/AppBoxPlugin/AppBoxPdHelper.cpp new file mode 100644 index 0000000..46e0fb9 --- /dev/null +++ b/src_mobile/Plugin/AppBoxPlugin/AppBoxPdHelper.cpp @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file AppBoxPdHelper.cpp + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#include <string> +#include <Evas.h> +#include <ewk_view.h> +#include <Core/Util/Log.h> +#include "AppBoxPdHelper.h" + +AppBoxPdHelper::AppBoxPdHelper(Evas_Object* pdWin) + : m_win(pdWin) + , m_boxWebView() + , m_pdWebView() + , m_opened(false) +{ +} + +AppBoxPdHelper::~AppBoxPdHelper() +{ +} + +void AppBoxPdHelper::startOpen() +{ + LogD("enter"); +} + +void AppBoxPdHelper::finishOpen(Evas_Object* child) +{ + LogD("enter"); + m_opened = true; + setPdWebView(child); +} + +void AppBoxPdHelper::close() +{ + LogD("enter"); +} + +void AppBoxPdHelper::setBoxWebView(Evas_Object* webview) +{ + LogD("enter"); + m_boxWebView = webview; +} + +void AppBoxPdHelper::setPdWebView(Evas_Object* webview) +{ + LogD("enter"); + m_pdWebView = webview; +} + +Evas_Object* AppBoxPdHelper::getBoxWebView() const +{ + LogD("enter"); + return m_boxWebView; +} + +Evas_Object* AppBoxPdHelper::getPdWebView() const +{ + LogD("enter"); + return m_pdWebView; +} + +Evas* AppBoxPdHelper::getPdCanvas() const +{ + LogD("enter"); + return evas_object_evas_get(m_win); +} + +bool AppBoxPdHelper::isPdOpened() const +{ + LogD("enter"); + return m_opened; +} diff --git a/src_mobile/Plugin/AppBoxPlugin/AppBoxPdHelper.h b/src_mobile/Plugin/AppBoxPlugin/AppBoxPdHelper.h new file mode 100644 index 0000000..ae49863 --- /dev/null +++ b/src_mobile/Plugin/AppBoxPlugin/AppBoxPdHelper.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file AppBoxPdHelper.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ + +#ifndef APP_BOX_PD_HELPER_H +#define APP_BOX_PD_HELPER_H + +#include <string> +#include <Evas.h> +#include <Core/View/IPdHelper.h> + +class AppBoxPdHelper: public IPdHelper { + public: + static IPdHelperPtr create(Evas_Object* pdWin) + { + return IPdHelperPtr(new AppBoxPdHelper(pdWin)); + } + virtual void startOpen(); + virtual void finishOpen(Evas_Object* child); + virtual void close(); + virtual void setBoxWebView(Evas_Object* webview); + virtual void setPdWebView(Evas_Object* webview); + virtual Evas_Object* getBoxWebView() const; + virtual Evas_Object* getPdWebView() const; + virtual Evas* getPdCanvas() const; + virtual bool isPdOpened() const; + virtual ~AppBoxPdHelper(); + + private: + AppBoxPdHelper(Evas_Object* pdWin); + + //members + Evas_Object* m_win; + Evas_Object* m_boxWebView; + Evas_Object* m_pdWebView; + bool m_opened; +}; + +#endif // APP_BOX_PD_HELPER_H diff --git a/src_mobile/Plugin/AppBoxPlugin/AppBoxPluginFactory.cpp b/src_mobile/Plugin/AppBoxPlugin/AppBoxPluginFactory.cpp new file mode 100644 index 0000000..8f0bfb2 --- /dev/null +++ b/src_mobile/Plugin/AppBoxPlugin/AppBoxPluginFactory.cpp @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file AppBoxPluginFactory.cpp + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#include <string> +#include <memory> +#include <Core/View/IRenderView.h> +#include <Core/Buffer/IRenderBuffer.h> +#include "AppBoxRenderView.h" +#include "AppBoxRenderBuffer.h" +#include "AppBoxPluginFactory.h" + +IRenderViewPtr AppBoxPluginFactory::createRenderView( + std::string boxId, std::string instanceId, + std::shared_ptr<Ewk_Context> ewkContext) +{ + return AppBoxRenderView::create(boxId, instanceId, ewkContext); +} + +IRenderBufferPtr AppBoxPluginFactory::createBoxRenderBuffer( + std::string boxId, std::string instanceId, + int width, int height, std::string data) +{ + // use appbox render buffer + return AppBoxRenderBuffer::create(boxId, instanceId, width, height, data); +} diff --git a/src_mobile/Plugin/AppBoxPlugin/AppBoxPluginFactory.h b/src_mobile/Plugin/AppBoxPlugin/AppBoxPluginFactory.h new file mode 100644 index 0000000..ca5a5f2 --- /dev/null +++ b/src_mobile/Plugin/AppBoxPlugin/AppBoxPluginFactory.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file AppBoxPluginFactory.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef APP_BOX_PLUGIN_FACTORY_H +#define APP_BOX_PLUGIN_FACTORY_H + +#include <string> +#include <memory> +#include <Plugin/IBoxPluginFactory.h> +#include <Core/View/IRenderView.h> +#include <Core/Buffer/IRenderBuffer.h> +#include <ewk_context.h> +#include <Evas.h> + +class AppBoxPluginFactory: public IBoxPluginFactory { + public: + IRenderViewPtr createRenderView( + std::string boxId, std::string instanceId, + std::shared_ptr<Ewk_Context> ewkContext); + + IRenderBufferPtr createBoxRenderBuffer( + std::string boxId, std::string instanceId, + int width, int height, std::string data); + + AppBoxPluginFactory() {}; + ~AppBoxPluginFactory() {}; +}; + +#endif //APP_BOX_PLUGIN_FACTORY_H diff --git a/src_mobile/Plugin/AppBoxPlugin/AppBoxRenderBuffer.cpp b/src_mobile/Plugin/AppBoxPlugin/AppBoxRenderBuffer.cpp new file mode 100644 index 0000000..f0c0ae0 --- /dev/null +++ b/src_mobile/Plugin/AppBoxPlugin/AppBoxRenderBuffer.cpp @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file AppBoxRenderBuffer.cpp + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#include <string> +#include <API/web_provider_livebox_info.h> +#include <Core/Buffer/RenderBuffer.h> +#include <Core/Util/Log.h> +#include <Core/Util/Util.h> +#include "AppBoxRenderView.h" +#include "AppBoxRenderBuffer.h" +#include "AppBoxObserver.h" + +#define MAX_WAIT_TIME 5.0 + +AppBoxRenderBuffer::AppBoxRenderBuffer( + std::string boxId, std::string instanceId, + int width, int height, std::string data) + : BoxRenderBuffer(boxId, instanceId, width, height) + , m_boxId(boxId) + , m_instanceId(instanceId) + , m_mouseEventRecievable(false) + , m_touchTimer() + , m_renderView() +{ + LogD("enter"); + UNUSED_PARAM(data); + + if (web_provider_livebox_get_mouse_event(m_boxId.c_str())) { + m_mouseEventRecievable = true; + } + + AppBoxObserver::Instance()->registerRenderBuffer(m_instanceId, this); +} + +AppBoxRenderBuffer::~AppBoxRenderBuffer() +{ + LogD("enter"); + AppBoxObserver::Instance()->unregisterRenderBuffer(m_instanceId); +} + +void AppBoxRenderBuffer::didHandleTouchEvent( + TouchType type, double timestamp, double x, double y) +{ + LogD("enter"); + if (!m_mouseEventRecievable) { + return; + } + + m_renderView = AppBoxObserver::Instance()->getRenderView(m_instanceId); + + if (!m_renderView || !(m_renderView->m_boxWrt)) { + LogD("no matched render view"); + return; + } + + // if needed, resume render view + if (m_renderView->m_fireRenderTimer) { + m_renderView->deleteTimer(&(m_renderView->m_fireRenderTimer)); + } else { + if (!m_touchTimer) { + startCanvasUpdate(); + + // temp condition + if (m_renderView->m_boxWrt_isSuspended == true) + { + m_renderView->m_boxWrt_isSuspended = false; + m_renderView->m_boxWrt->Resume(); + } + } else { + deleteTouchTimer(); + } + } + + BoxRenderBuffer::didHandleTouchEvent(type, timestamp, x, y); + m_touchTimer = ecore_timer_add(MAX_WAIT_TIME, fireTouchTimerCallback, this); +} + +void AppBoxRenderBuffer::deleteTouchTimer() +{ + LogD("enter"); + if (m_touchTimer) { + ecore_timer_del(m_touchTimer); + m_touchTimer = NULL; + } +} + +Eina_Bool AppBoxRenderBuffer::fireTouchTimerCallback(void* data) +{ + LogD("enter"); + AppBoxRenderBuffer* This = static_cast<AppBoxRenderBuffer*>(data); + This->stopCanvasUpdate(); + + // temp condition + if (This->m_renderView->m_boxWrt_isSuspended == false) + { + This->m_renderView->m_boxWrt_isSuspended = true; + This->m_renderView->m_boxWrt->Suspend(); + } + + This->m_touchTimer = NULL; + + return ECORE_CALLBACK_CANCEL; +} diff --git a/src_mobile/Plugin/AppBoxPlugin/AppBoxRenderBuffer.h b/src_mobile/Plugin/AppBoxPlugin/AppBoxRenderBuffer.h new file mode 100644 index 0000000..ba8462a --- /dev/null +++ b/src_mobile/Plugin/AppBoxPlugin/AppBoxRenderBuffer.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file AppBoxRenderBuffer.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef APP_BOX_RENDER_BUFFER_H +#define APP_BOX_RENDER_BUFFER_H + +#include <string.h> +#include <Core/Buffer/BoxRenderBuffer.h> + +struct _Ecore_Timer; +typedef _Ecore_Timer Ecore_Timer; + +class AppBoxRenderBuffer: public BoxRenderBuffer { + public: + static IRenderBufferPtr create( + std::string boxId, std::string instanceId, + int width, int height, std::string data) + { + return IRenderBufferPtr(new AppBoxRenderBuffer( + boxId, instanceId, width, height, data)); + } + ~AppBoxRenderBuffer(); + + private: + void didHandleTouchEvent( + TouchType type, double timestamp, double x, double y); + void deleteTouchTimer(); + static Eina_Bool fireTouchTimerCallback(void* data); + + AppBoxRenderBuffer( + std::string boxId, std::string instanceId, + int width, int height, std::string data); + + // members + std::string m_boxId; + std::string m_instanceId; + bool m_mouseEventRecievable; + Ecore_Timer* m_touchTimer; + AppBoxRenderView* m_renderView; + + friend class AppBoxRenderView; +}; + +#endif // APP_BOX_RENDER_BUFFER_H diff --git a/src_mobile/Plugin/AppBoxPlugin/AppBoxRenderView.cpp b/src_mobile/Plugin/AppBoxPlugin/AppBoxRenderView.cpp new file mode 100755 index 0000000..891e5bb --- /dev/null +++ b/src_mobile/Plugin/AppBoxPlugin/AppBoxRenderView.cpp @@ -0,0 +1,683 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file AppBoxRenderView.cpp + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#include <sys/types.h> +#include <unistd.h> +#include <string> +#include <fstream> +#include <streambuf> +#include <aul.h> +#include <Eina.h> +#include <Evas.h> +#include <Ecore.h> +#include <EWebKit2.h> +#include <ewk_view.h> +#include <ewk_context.h> +#include <ewk_settings.h> +#include <livebox-service.h> +#include <i_runnable_widget_object.h> +#include <core_module.h> +#include <dpl/fast_delegate.h> +#include <Core/BoxSchemeHandler.h> +#include <Core/View/IRenderView.h> +#include <Core/View/IPdHelper.h> +#include <Core/View/PdHelper.h> +#include <API/web_provider_livebox_info.h> +#include <Core/Util/Log.h> +#include <Core/Util/Util.h> +#include "AppBoxObserver.h" +#include "AppBoxRenderBuffer.h" +#include "AppBoxPdHelper.h" +#include "AppBoxRenderView.h" + +#define RENDER_MAX_TIME 30.0 +#define SNAPSHOT_REMOVE_TIME 1.0 +#define WEB_DBOX_OBJ_MOVE_TO_OUTSIDE_POINT_VALUE -10000 + +// injection javascript file regarding creating js object used by box and pd +static const std::string injectionFile("/usr/share/web-provider/injection.js"); + +AppBoxRenderView::AppBoxRenderView( + std::string boxId, std::string instanceId, + EwkContextPtr ewkContext) + : m_appId() + , m_boxId(boxId) + , m_instanceId(instanceId) + , m_ewkContext(ewkContext) + , m_boxRenderInfo() + , m_boxWrt() + , m_pdWrt() + , m_snapshot() + , m_fireRenderTimer() + , m_removeSnapShotTimer() + , m_pdHelper() + , m_boxRenderBuffer() + , m_pdFastOpen(false) + , m_boxFinishLoad(false) + , m_boxFrameRendered(false) + , m_boxWrt_isSuspended(false) +{ + LogD("enter"); + m_appId = getAppId(m_boxId); + if (m_appId.empty()) { + throw; //exception throw! + } + + m_boxRenderBuffer = AppBoxObserver::Instance()->getRenderBuffer(m_instanceId); + + // use fastopen to default + // m_pdFastOpen = web_provider_livebox_get_pd_fast_open(m_boxId.c_str()) ? true : false; + m_pdFastOpen = true; + AppBoxObserver::Instance()->registerRenderView(m_instanceId, this); +} + +AppBoxRenderView::~AppBoxRenderView() +{ + LogD("enter"); + + destroyWrtCore(m_boxWrt); + destroyWrtCore(m_pdWrt); + AppBoxObserver::Instance()->unregisterRenderView(m_instanceId); +} + +void AppBoxRenderView::showBox(RenderInfoPtr boxRenderInfo) +{ + LogD("enter"); + + // stop updating render buffer + m_boxRenderBuffer->stopCanvasUpdate(); + + // clear snapshot if this is not the case of pd open + if (!m_pdHelper) { + clearSnapShot(); + } + + // delete already running timer + deleteTimer(&m_fireRenderTimer); + + // delete touch timer + if (web_provider_livebox_get_mouse_event(m_boxId.c_str())) { + m_boxRenderBuffer->deleteTouchTimer(); + } + + // set boxFinishLoad and m_boxFrameRendered to false + m_boxFinishLoad = false; + m_boxFrameRendered = false; + + // copy to url + std::string boxStartUrl = getStartUrl(URL_TYPE_BOX, boxRenderInfo->defaultUrlParams); + if (m_boxWrt) { + LogD("existing wrt core is removed"); + destroyBoxWrtCore(); + } + + m_boxWrt = createWrtCore( + URL_TYPE_BOX, boxStartUrl, + boxRenderInfo->window, m_ewkContext); + m_boxWrt_isSuspended = false; + + // in case of showing box by request of pd open + if (m_pdHelper) { + m_pdHelper->setBoxWebView(m_boxWrt->GetCurrentWebview()); + } + + // resize webview fitted to width, height of Box + evas_object_resize( + m_boxWrt->GetCurrentWebview(), + boxRenderInfo->width, + boxRenderInfo->height); + + + evas_object_show(m_boxWrt->GetCurrentWebview()); + // webview window move to outside of viewport because of overlap issue with snapshot image + evas_object_move(m_boxWrt->GetCurrentWebview(), WEB_DBOX_OBJ_MOVE_TO_OUTSIDE_POINT_VALUE, WEB_DBOX_OBJ_MOVE_TO_OUTSIDE_POINT_VALUE); + + m_boxWrt->Show(); + m_boxRenderInfo = boxRenderInfo; +} + +AppBoxRenderView::WrtCorePtr AppBoxRenderView::createWrtCore( + UrlType type, std::string& startUrl, + Evas_Object* win, EwkContextPtr ewkContext) +{ + LogD("enter"); + + WrtCorePtr wrt; + wrt = WRT::CoreModuleSingleton:: + Instance().getRunnableWidgetObject(m_appId); + // prepare webview + if (startUrl.empty()) { + LogD("no start url"); + return WrtCorePtr(); + } + wrt->PrepareView(startUrl, win, ewkContext.get()); + wrt->CheckBeforeLaunch(); + + // set callback functions of RunnableWidgetObject + WRT::UserDelegatesPtr cbs(new WRT::UserDelegates); + cbs->loadStart = DPL::MakeDelegate(this, &AppBoxRenderView::startLoadCallback); + if (type == URL_TYPE_BOX) { + cbs->loadFinish = DPL::MakeDelegate(this, &AppBoxRenderView::finishBoxLoadCallback); + } else { + cbs->loadFinish = DPL::MakeDelegate(this, &AppBoxRenderView::finishPdLoadCallback); + } + + cbs->bufferSet = DPL::MakeDelegate(this, &AppBoxRenderView::setBufferCallback); + cbs->bufferUnset = DPL::MakeDelegate(this, &AppBoxRenderView::unsetBufferCallback); + if (!m_pdFastOpen) { + cbs->windowCreateBefore = + DPL::MakeDelegate(this, &AppBoxRenderView::createWindowBeforeCallback); + cbs->windowCreateAfter = + DPL::MakeDelegate(this, &AppBoxRenderView::createWindowAfterCallback); + } + + cbs->navigationDecide = + DPL::MakeDelegate(this, &AppBoxRenderView::decideNavigationCallback); + cbs->webCrash = DPL::MakeDelegate(this, &AppBoxRenderView::crashWebProcessCallback); + wrt->SetUserDelegates(cbs); + + // set basic webview setting + setWebViewBasicSetting(wrt->GetCurrentWebview()); + return wrt; +} + +void AppBoxRenderView::destroyBoxWrtCore() +{ + LogD("enter"); + + m_boxRenderBuffer->stopCanvasUpdate(); + deleteTimer(&m_fireRenderTimer); + deleteTimer(&m_removeSnapShotTimer); + destroyWrtCore(m_boxWrt); + m_boxWrt.reset(); + + // temp + m_boxWrt_isSuspended = false; +} + +void AppBoxRenderView::destroyPdWrtCore() +{ + LogD("enter"); + + destroyWrtCore(m_pdWrt); + m_pdWrt.reset(); +} + +void AppBoxRenderView::destroyWrtCore(WrtCorePtr wrt) +{ + LogD("enter"); + + if (wrt) { + wrt->Hide(); + } +} + +void AppBoxRenderView::hideBox() +{ + LogD("enter"); + destroyBoxWrtCore(); + if (m_boxRenderInfo->window) { + evas_object_hide(m_boxRenderInfo->window); + } +} + +void AppBoxRenderView::pauseBox() +{ + LogD("enter"); +} + +void AppBoxRenderView::resumeBox() +{ + LogD("enter"); +} + +void AppBoxRenderView::showPd(RenderInfoPtr pdRenderInfo, RenderInfoPtr boxRenderInfo) +{ + LogD("enter"); + + std::string pdStartUrl = getStartUrl(URL_TYPE_PD, pdRenderInfo->defaultUrlParams); + if (m_pdFastOpen) { + destroyPdWrtCore(); + // if you want to launch new Web Process for PD, use the following line. + // EwkContextPtr pdContext = AppBoxObserver::Instance()->getPdEwkContext(); + m_pdWrt = createWrtCore(URL_TYPE_PD, pdStartUrl, pdRenderInfo->window, m_ewkContext); + if (!m_pdWrt) { + LogD("no wrt core instance"); + return; + } + m_pdHelper = AppBoxPdHelper::create(pdRenderInfo->window); + + // resize webview fitted to width, height of pd + evas_object_resize( + m_pdWrt->GetCurrentWebview(), + pdRenderInfo->width, + pdRenderInfo->height); + // show pd + m_pdWrt->Show(); + m_pdHelper->finishOpen(m_pdWrt->GetCurrentWebview()); + } else { + m_pdHelper = PdHelper::create(pdRenderInfo, pdStartUrl); + } + + // show pd window + evas_object_show(pdRenderInfo->window); + + // need to create new snapshot when m_napshot is empty + if (!m_snapshot) { + evas_object_show(getCurrentSnapShot()); + } + + // show box + showBox(boxRenderInfo); + + // start timer for clearing existing snapshot in case of only pd open + addTimer(&m_removeSnapShotTimer, SNAPSHOT_REMOVE_TIME, removeSnapShotTimerCallback); + +} + +void AppBoxRenderView::hidePd() +{ + LogD("enter"); + + if (m_pdFastOpen) { + destroyPdWrtCore(); + } + m_pdHelper->close(); + m_pdHelper.reset(); + + // start timer for clearing existing snapshot in case of only pd open + addTimer(&m_fireRenderTimer, RENDER_MAX_TIME, fireRenderTimerCallback); +} + +Evas_Object* AppBoxRenderView::getBoxWebView() +{ + if (!m_pdHelper) { + return m_boxWrt->GetCurrentWebview(); + } else { + // Here, we can't use GetCurrentWebView() of wrt-core to get Box' webview, + // because in the non fast-open, GetCurrentWebview() returns PD's webview. + return m_pdHelper->getBoxWebView(); + } +} + +Evas_Object* AppBoxRenderView::getPdWebView() +{ + if (!m_pdHelper) { + return NULL; + } + + return m_pdHelper->getPdWebView(); +} + +std::string AppBoxRenderView::getAppId(std::string& boxId) +{ + LogD("enter"); + + const char* appId = web_provider_livebox_get_app_id(boxId.c_str()); + if (!appId) { + LogD("no appid of %s", boxId.c_str()); + return std::string(); + } + + return std::string(appId); +} + +std::string AppBoxRenderView::getStartUrl(UrlType type, std::string& defaultParams) +{ + const char* path; + switch (type) { + case URL_TYPE_BOX: + path = livebox_service_lb_script_path(m_boxId.c_str()); + break; + case URL_TYPE_PD: + path = livebox_service_pd_script_path(m_boxId.c_str()); + break; + default: + LogD("no available type"); + } + + std::string startUrl; + if (path) { + LogD("path : %s", path); + startUrl = path; + } else { + // TODO In this case, fallback page will be loaded. + LogE("Fail to get service lib script path"); + } + + // add default parameters to start url + startUrl += defaultParams; + + return startUrl; +} + +Evas_Object* AppBoxRenderView::getCurrentSnapShot() +{ + LogD("enter"); + clearSnapShot(); + m_snapshot = m_boxRenderBuffer->getSnapshot(); + + return m_snapshot; +} + +void AppBoxRenderView::clearSnapShot() +{ + LogD("enter"); + if (m_snapshot) { + evas_object_del(m_snapshot); + m_snapshot = NULL; + } +} + +void AppBoxRenderView::showSnapShot() +{ + LogD("enter"); + if (m_snapshot) { + evas_object_raise(m_snapshot); + evas_object_show(m_snapshot); + } +} + +void AppBoxRenderView::hideSnapShot() +{ + LogD("enter"); + if (m_snapshot) { + evas_object_hide(m_snapshot); + evas_object_lower(m_snapshot); + } +} + +void AppBoxRenderView::addTimer(Ecore_Timer** timer, double interval, Ecore_Task_Cb callback) +{ + LogD("enter"); + if (*timer) { + deleteTimer(timer); + } + + *timer = ecore_timer_add(interval, callback, this); +} + +void AppBoxRenderView::deleteTimer(Ecore_Timer** timer) +{ + LogD("enter"); + if (*timer) { + ecore_timer_del(*timer); + *timer = NULL; + } +} + +void AppBoxRenderView::stopRenderBox() +{ + deleteTimer(&m_fireRenderTimer); + m_boxRenderBuffer->stopCanvasUpdate(); + if (web_provider_livebox_get_mouse_event(m_boxId.c_str())) { + // stop touch timer + m_boxRenderBuffer->deleteTouchTimer(); + + // temp condition + if (m_boxWrt_isSuspended == false) + { + m_boxWrt_isSuspended = true; + m_boxWrt->Suspend(); + } + } else { + // Before webview should be removed, + // new evas object with last render data should be created + // otherwise, after webview is removed, box is white screen. + evas_object_show(getCurrentSnapShot()); + destroyBoxWrtCore(); + } +} + +void AppBoxRenderView::setWebViewBasicSetting(Evas_Object* webview) +{ + LogD("enter"); + + if (!webview) { + return; + } + Ewk_Settings* setting = ewk_view_settings_get(webview); + // Disable ime features + ewk_settings_default_keypad_enabled_set(setting, EINA_FALSE); + // To support transparent background + evas_object_color_set(webview, 0, 0, 0, 1); + ewk_view_draws_transparent_background_set(webview, EINA_TRUE); + ewk_view_visibility_set(webview, EINA_TRUE); + + // To know starting point for updating buffer + evas_object_smart_callback_add( + webview, + "load,nonemptylayout,finished", + loadNonEmptyLayoutFinishedCallback, + this); + evas_object_smart_callback_add( + webview, + "frame,rendered", + frameRenderedCallback, + this); + // To set font type whenever font changed + ewk_view_use_settings_font(webview); +} + +Eina_Bool AppBoxRenderView::fireRenderTimerCallback(void* data) +{ + LogD("enter"); + + AppBoxRenderView* This = static_cast<AppBoxRenderView*>(data); + This->m_fireRenderTimer = NULL; + This->stopRenderBox(); + + return ECORE_CALLBACK_CANCEL; +} + +Eina_Bool AppBoxRenderView::removeSnapShotTimerCallback(void* data) +{ + LogD("enter"); + + AppBoxRenderView* This = static_cast<AppBoxRenderView*>(data); + if (!(This->m_boxFinishLoad && This->m_boxFrameRendered)) { + return ECORE_CALLBACK_RENEW; + } + + // hide snapshot because valid frame has been prepared generally. + This->clearSnapShot(); + + // move to inside of viewport to prevent overlap with snapshot image + evas_object_move(This->m_boxWrt->GetCurrentWebview(), 0, 0); + evas_object_show(This->m_boxWrt->GetCurrentWebview()); + + This->m_removeSnapShotTimer = NULL; + return ECORE_CALLBACK_CANCEL; +} + +Eina_Bool AppBoxRenderView::openPdIdlerCallback(void* data) +{ + LogD("enter"); + AppBoxRenderView* This = static_cast<AppBoxRenderView*>(data); + if (This && This->m_pdHelper) { + This->m_pdHelper->startOpen(); + } + return ECORE_CALLBACK_CANCEL; +} + +void AppBoxRenderView::executeScriptCallback( + Evas_Object* webview, const char* result, void* data) +{ + LogD("enter"); + UNUSED_PARAM(webview); + UNUSED_PARAM(data); + + std::string resultStr(result ? result : "null"); + LogD("result: %s", resultStr.c_str()); +} + +void AppBoxRenderView::startLoadCallback(Evas_Object* webview) +{ + LogD("enter"); + if(!webview) { + return; + } + // execute injection for creating js objects + std::ifstream jsFile(injectionFile); + std::string script((std::istreambuf_iterator<char>(jsFile)), + std::istreambuf_iterator<char>()); + + LogD("injected js code: %s", script.c_str()); + ewk_view_script_execute(webview, script.c_str(), executeScriptCallback, this); +} + +void AppBoxRenderView::finishBoxLoadCallback(Evas_Object* webview) +{ + LogD("enter"); + if (!webview) { + return; + } + + ewk_view_visibility_set(webview, EINA_TRUE); + + if (!m_pdHelper) { + // start render timer + addTimer(&m_fireRenderTimer, RENDER_MAX_TIME, fireRenderTimerCallback); + } else { + if (!m_pdFastOpen) { + if (!(m_pdHelper->isPdOpened()) && + webview == m_pdHelper->getBoxWebView()) + { + // open pd + ecore_idler_add(openPdIdlerCallback, this); + } + } + } + + // set flag + m_boxFinishLoad = true; +} + +void AppBoxRenderView::finishPdLoadCallback(Evas_Object* webview) +{ + LogD("enter"); + if (!webview) { + return; + } + + ewk_view_visibility_set(webview, EINA_TRUE); +} + +void AppBoxRenderView::createWindowBeforeCallback(Evas** canvas, Evas_Object* parent) +{ + LogD("enter"); + + if (m_pdHelper) { + if (!(m_pdHelper->isPdOpened()) && + parent == m_pdHelper->getBoxWebView()) + { + LogD("pd canvas is used"); + *canvas = m_pdHelper->getPdCanvas(); + return; + } + } + + LogD("canvas of this webview is used"); + *canvas = evas_object_evas_get(parent); +} + +void AppBoxRenderView::createWindowAfterCallback(Evas_Object* parent, Evas_Object* child) +{ + LogD("enter"); + if (!parent) { + return; + } + + if (m_pdHelper) { + Evas* parentCanvas = evas_object_evas_get(parent); + Evas* childCanvas = evas_object_evas_get(child); + + if (parentCanvas != childCanvas) { + // wrt-core change visibility value to false internally + // So plugin should reset this value to true for painting parent webview + ewk_view_visibility_set(parent, EINA_TRUE); + evas_object_show(parent); + m_pdHelper->finishOpen(child); + } + } + + setWebViewBasicSetting(child); + evas_object_show(child); +} + +void AppBoxRenderView::setBufferCallback(Evas_Object* webview) +{ + LogD("enter"); + evas_object_show(webview); + evas_object_focus_set(webview, EINA_TRUE); +} + +void AppBoxRenderView::unsetBufferCallback(Evas_Object* webview) +{ + LogD("enter"); + evas_object_hide(webview); +} + +void AppBoxRenderView::decideNavigationCallback(Evas_Object* webview, std::string& uri) +{ + LogD("enter"); + UNUSED_PARAM(webview); + + // navigation of box scheme should be ignored + if(BoxSchemeHandler::Instance()->isBoxScheme(uri)) { + LogD("box scheme"); + BoxSchemeHandler::Instance()->process(m_instanceId, uri); + } +} + +void AppBoxRenderView::crashWebProcessCallback() +{ + LogD("enter"); + elm_exit(); +} + +void AppBoxRenderView::loadNonEmptyLayoutFinishedCallback( + void* data, Evas_Object* webview, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(data); + UNUSED_PARAM(webview); + UNUSED_PARAM(eventInfo); +} + +void AppBoxRenderView::frameRenderedCallback( + void* data, Evas_Object* webview, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(webview); + UNUSED_PARAM(eventInfo); + + // start to update render buffer! + AppBoxRenderView* This = static_cast<AppBoxRenderView*>(data); + This->m_boxRenderBuffer->startCanvasUpdate(); + + // set flag + This->m_boxFrameRendered = true; + + // move to inside of viewport to prevent overlap with snapshot image + if (!This->m_removeSnapShotTimer) { + evas_object_move(This->m_boxWrt->GetCurrentWebview(), 0, 0); + } + +} diff --git a/src_mobile/Plugin/AppBoxPlugin/AppBoxRenderView.h b/src_mobile/Plugin/AppBoxPlugin/AppBoxRenderView.h new file mode 100644 index 0000000..4d0d7a7 --- /dev/null +++ b/src_mobile/Plugin/AppBoxPlugin/AppBoxRenderView.h @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file AppBoxRenderView.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef APP_BOX_RENDER_VIEW_H +#define APP_BOX_RENDER_VIEW_H + +#include <string> +#include <memory> +#include <Eina.h> +#include <Ecore.h> +#include <Evas.h> +#include <ewk_context.h> +#include <i_runnable_widget_object.h> +#include <Core/View/IRenderView.h> +#include <Core/View/IPdHelper.h> + +class AppBoxRenderBuffer; + +class AppBoxRenderView: public IRenderView { + public: + typedef std::shared_ptr<Ewk_Context> EwkContextPtr; + + static IRenderViewPtr create( + std::string boxId, std::string instanceId, + EwkContextPtr ewkContext) + { + return IRenderViewPtr( + new AppBoxRenderView( + boxId, instanceId, ewkContext)); + }; + virtual void showBox(RenderInfoPtr boxRenderInfo); + virtual void hideBox(); + virtual void pauseBox(); + virtual void resumeBox(); + virtual void showPd(RenderInfoPtr pdRenderInfo, RenderInfoPtr boxRenderInfo); + virtual void hidePd(); + Evas_Object* getBoxWebView(); + Evas_Object* getPdWebView(); + virtual ~AppBoxRenderView(); + + private: + // type definition + typedef std::shared_ptr<WRT::IRunnableWidgetObject> WrtCorePtr; + enum UrlType { + URL_TYPE_BOX, + URL_TYPE_PD + }; + + WrtCorePtr createWrtCore( + UrlType type, std::string& startUrl, + Evas_Object* win, EwkContextPtr ewkContext); + void setWebViewBasicSetting(Evas_Object* webview); + void destroyWrtCore(WrtCorePtr wrt); + void destroyBoxWrtCore(); + void destroyPdWrtCore(); + std::string getAppId(std::string& boxId); + std::string getStartUrl(UrlType type, std::string& defaultParams); + Evas_Object* getCurrentSnapShot(); + void clearSnapShot(); + void showSnapShot(); + void hideSnapShot(); + void addTimer(Ecore_Timer** timer, double interval, Ecore_Task_Cb callback); + void deleteTimer(Ecore_Timer** timer); + void stopRenderBox(); + + // timer and idler callback + static Eina_Bool fireRenderTimerCallback(void* data); + static Eina_Bool removeSnapShotTimerCallback(void* data); + static Eina_Bool openPdIdlerCallback(void* data); + + // ewk view callback + static void executeScriptCallback( + Evas_Object* webview, const char* result, void* data); + static void loadNonEmptyLayoutFinishedCallback( + void* data, Evas_Object* webview, void* eventInfo); + static void frameRenderedCallback( + void* data, Evas_Object* webview, void* eventInfo); + + // user Callbacks of RunnableWidgetObject + void startLoadCallback(Evas_Object* webview); + void finishBoxLoadCallback(Evas_Object* webview); + void finishPdLoadCallback(Evas_Object* webview); + void createWindowBeforeCallback(Evas** canvas, Evas_Object* parent); + void createWindowAfterCallback(Evas_Object* parent, Evas_Object* child); + void setBufferCallback(Evas_Object* webview); + void unsetBufferCallback(Evas_Object* webview); + void decideNavigationCallback(Evas_Object* webview, std::string& uri); + void crashWebProcessCallback(); + + // constructor + explicit AppBoxRenderView( + std::string boxId, std::string instanceId, + EwkContextPtr ewkContext); + + // members + std::string m_appId; + std::string m_boxId; + std::string m_instanceId; + EwkContextPtr m_ewkContext; + RenderInfoPtr m_boxRenderInfo; + WrtCorePtr m_boxWrt; + WrtCorePtr m_pdWrt; + Evas_Object* m_snapshot; + Ecore_Timer* m_fireRenderTimer; + Ecore_Timer* m_removeSnapShotTimer; + IPdHelperPtr m_pdHelper; + AppBoxRenderBuffer* m_boxRenderBuffer; + + // for check status of webview + bool m_pdFastOpen; + bool m_boxFinishLoad; + bool m_boxFrameRendered; + + // TODO this temporary flag should removed! + bool m_boxWrt_isSuspended; + + friend class AppBoxRenderBuffer; +}; + +#endif // APP_BOX_RENDER_VIEW_H diff --git a/src_mobile/Plugin/AppBoxPlugin/CMakeLists.txt b/src_mobile/Plugin/AppBoxPlugin/CMakeLists.txt new file mode 100644 index 0000000..a072064 --- /dev/null +++ b/src_mobile/Plugin/AppBoxPlugin/CMakeLists.txt @@ -0,0 +1,75 @@ +# Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved +# +# Licensed under the Flora License, Version 1.1 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://floralicense.org/license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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) + +SET(TARGET_NAME web-provider-plugin-app) +SET(DEPS ${TARGET_NAME}_DEPS) + +PKG_CHECK_MODULES(${DEPS} + ail + ewebkit2 + wrt-core + dpl-efl + evas + ecore + eina + livebox-service + dlog + provider # this should be removed + REQUIRED +) +ADD_DEFINITIONS(${${DEPS}_CFLAGS}) + +SET(SRCS + ${CMAKE_CURRENT_SOURCE_DIR}/box_plugin_interface.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/AppBoxManager.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/AppBoxObserver.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/AppBoxPluginFactory.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/AppBoxRenderView.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/AppBoxRenderBuffer.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/AppBoxPdHelper.cpp +) + +SET(HEADERS + ${${DEPS}_INCLUDE_DIRS} + ${CMAKE_CURRENT_SOURCE_DIR} +) +INCLUDE_DIRECTORIES(${HEADERS}) + +ADD_LIBRARY(${TARGET_NAME} SHARED ${SRCS}) + +SET_TARGET_PROPERTIES(${TARGET_NAME} PROPERTIES + COMPILE_FLAGS -fPIC + LINK_FLAGS "-Wl,--as-needed -Wl,--hash-style=both" +) + +SET_TARGET_PROPERTIES(${TARGET_NAME} + PROPERTIES + SOVERSION ${CMAKE_PROJECT_API_VERSION} + VERSION ${CMAKE_PROJECT_VERSION} +) + +TARGET_LINK_LIBRARIES(${TARGET_NAME} + ${${DEPS}_LIBRARIES} + ${TARGET_CORE} +) + +INSTALL(TARGETS ${TARGET_NAME} + DESTINATION lib/${PROJECT_NAME} + PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE + GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE +) + +INSTALL_FILE(app.json lib/${PROJECT_NAME}) diff --git a/src_mobile/Plugin/AppBoxPlugin/app.json b/src_mobile/Plugin/AppBoxPlugin/app.json new file mode 100644 index 0000000..6388702 --- /dev/null +++ b/src_mobile/Plugin/AppBoxPlugin/app.json @@ -0,0 +1,5 @@ +{ + "type" : "app", + "path" : "/usr/lib/web-provider/libweb-provider-plugin-app.so", + "supported_size" : ["1x1","2x1","2x2"] +} diff --git a/src_mobile/Plugin/AppBoxPlugin/box_plugin_interface.cpp b/src_mobile/Plugin/AppBoxPlugin/box_plugin_interface.cpp new file mode 100644 index 0000000..ca5e65e --- /dev/null +++ b/src_mobile/Plugin/AppBoxPlugin/box_plugin_interface.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file box_plugin_interface.cpp + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#include <memory> +#include <Core/BoxData.h> +#include <Core/Util/Log.h> +#include <Plugin/box_plugin_interface.h> +#include "AppBoxManager.h" +#include "AppBoxPluginFactory.h" + +static std::shared_ptr<IBoxManager> g_manager; + +int web_provider_plugin_interface_initialize() +{ + LogD("enter"); + IBoxPluginFactoryPtr factory(new AppBoxPluginFactory()); + g_manager = AppBoxManager::create(factory); + + return 0; +} + +int web_provider_plugin_interface_command(const request_cmd_type type, const BoxInfoPtr& boxInfo) +{ + LogD("enter"); + int ret = g_manager->doCommand(type, boxInfo); + + if (!ret) { + return -1; + } + + return 0; +} + +int web_provider_plugin_interface_shutdown() +{ + LogD("enter"); + g_manager.reset(); + return 0; +} diff --git a/src_mobile/Plugin/BoxPluginConnector.cpp b/src_mobile/Plugin/BoxPluginConnector.cpp new file mode 100644 index 0000000..a0cc23a --- /dev/null +++ b/src_mobile/Plugin/BoxPluginConnector.cpp @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file BoxPluginConnector.cpp + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#include <map> +#include <dlfcn.h> +#include <Core/Util/Log.h> +#include <Core/BoxData.h> +#include <API/web_provider_plugin_info.h> +#include "box_plugin_interface.h" +#include "BoxPluginConnector.h" + +BoxPluginConnector::BoxPluginConnector() +{ +} + +BoxPluginConnector::~BoxPluginConnector() +{ +} + +bool BoxPluginConnector::initialize() +{ + LogD("enter"); + + int count; + web_provider_plugin_info** pluginList = NULL; + pluginList = web_provider_plugin_get_installed_list(&count); + + if (!pluginList) { + LogD("failed to get installed plugin's information"); + return false; + } + + if (count <= 0) { + LogD("There is no available livebox plugins"); + return false; + } + + m_pluginMap.clear(); + + // get information of installed plugin + LogD("get information of installed plugin"); + for (int i = 0; i < count; i++) { + if (!pluginList[i]) { + continue; + } + + LogD("plugin path: %s", pluginList[i]->path); + void* handle = dlopen(pluginList[i]->path, RTLD_LAZY); + if (!handle) { + LogD("failed to load plugin so: %s", dlerror()); + continue; + } + + std::shared_ptr<plugin_interfaces> pluginInfo(new plugin_interfaces); + + pluginInfo->handle = handle; + pluginInfo->service_boxid = NULL; + if (pluginList[i]->service_boxid) { + pluginInfo->service_boxid = strdup(pluginList[i]->service_boxid); + } + + pluginInfo->initialize = + reinterpret_cast<plugin_interface_func_initialize>( + dlsym(handle, WEB_PROVIDER_PLUGIN_INTERFACE_SYM_INITIALIZE)); + pluginInfo->command = + reinterpret_cast<plugin_interface_func_command>( + dlsym(handle, WEB_PROVIDER_PLUGIN_INTERFACE_SYM_COMMAND)); + pluginInfo->shutdown = + reinterpret_cast<plugin_interface_func_shutdown>( + dlsym(handle, WEB_PROVIDER_PLUGIN_INTERFACE_SYM_SHUTDOWN)); + + if (!pluginInfo->initialize || !pluginInfo->command || + !pluginInfo->shutdown) + { + LogD("symbol for plugin interface is not found"); + continue; + } + + m_pluginMap[std::string(pluginList[i]->type)] = pluginInfo; + } + + // initialize plugins + for (auto it = m_pluginMap.begin(); + it != m_pluginMap.end(); ++it) + { + if (it->second) { + // TODO add exception or abnormal action on loading plugin + if (it->second->initialize() < 0) { + LogD("fail to intialize plugin"); + continue; + } + } + } + + // release information + LogD("release json data of plugins"); + web_provider_plugin_release_installed_list(pluginList, count); + + return true; +} + +bool BoxPluginConnector::shutdown() +{ + LogD("enter"); + // if needed, unload each plugin's DSO. + for (auto it = m_pluginMap.begin(); + it != m_pluginMap.end(); ++it) + { + if (it->second) { + it->second->shutdown(); + dlclose(it->second->handle); + } + } + + return true; +} + +bool BoxPluginConnector::requestCommand( + const request_cmd_type type, const BoxInfoPtr& boxInfo) +{ + LogD("enter"); + + // in case of request of resume all or pause all, all plugins should handle that. + if (type == REQUEST_CMD_RESUME_ALL || + type == REQUEST_CMD_PAUSE_ALL || + type == REQUEST_CMD_CHANGE_LANGUAGE) { + for (auto it = m_pluginMap.begin(); + it != m_pluginMap.end(); ++it) + { + if (it->second) { + it->second->command(type, boxInfo); + } + } + return true; + } + + const std::shared_ptr<plugin_interfaces> plugin = m_pluginMap[boxInfo->boxType]; + if (!plugin) { + LogD("not available livebox type"); + return false; + } + + int ret = plugin->command(type, boxInfo); + if (ret < 0) { + LogD("failed to request command"); + return false; + } + + return true; +} + +std::string BoxPluginConnector::getBoxType(const std::string& serviceBoxId) +{ + LogD("enter"); + + std::string type; + for (auto it = m_pluginMap.begin(); + it != m_pluginMap.end(); ++it) + { + if (it->second && it->second->service_boxid) { + if (serviceBoxId == it->second->service_boxid) { + LogD("service box id is matched!: %s", it->first.c_str()); + type = it->first; + break; + } + } + } + + return type; +} diff --git a/src_mobile/Plugin/BoxPluginConnector.h b/src_mobile/Plugin/BoxPluginConnector.h new file mode 100644 index 0000000..5ada8db --- /dev/null +++ b/src_mobile/Plugin/BoxPluginConnector.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file BoxPluginConnector.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef BOX_PLUGIN_CONNECTOR_H +#define BOX_PLUGIN_CONNECTOR_H + +#include <map> +#include <Core/BoxData.h> +#include "IBoxPluginConnector.h" +#include "box_plugin_interface.h" + +class BoxPluginConnector: public IBoxPluginConnector { + public: // IBoxPluginConnector + static IBoxPluginConnectorPtr create() + { + return IBoxPluginConnectorPtr(new BoxPluginConnector()); + }; + virtual bool initialize(); + virtual bool shutdown(); + virtual bool requestCommand( + const request_cmd_type type, const BoxInfoPtr& boxInfo); + virtual std::string getBoxType(const std::string& serviceBoxId); + virtual ~BoxPluginConnector(); + + private: + BoxPluginConnector(); + + // type definition + typedef std::map<std::string, std::shared_ptr<plugin_interfaces> > pluginMap; + + pluginMap m_pluginMap; + +}; + +#endif // BOX_PLUGIN_CONNECTOR_H diff --git a/src_mobile/Plugin/CMakeLists.txt b/src_mobile/Plugin/CMakeLists.txt new file mode 100644 index 0000000..349ddb0 --- /dev/null +++ b/src_mobile/Plugin/CMakeLists.txt @@ -0,0 +1,67 @@ +# Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved +# +# Licensed under the Flora License, Version 1.1 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://floralicense.org/license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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) + +SET(TARGET_NAME ${TARGET_PLUGIN}) +SET(DEPS ${TARGET_NAME}_DEPS) + +PKG_CHECK_MODULES(${DEPS} + evas + ewebkit2 + dlog + REQUIRED +) +ADD_DEFINITIONS(${${DEPS}_CFLAGS}) + +SET(SRCS + ${CMAKE_CURRENT_SOURCE_DIR}/BoxPluginConnector.cpp +) + +SET(HEADERS + ${${DEPS}_INCLUDE_DIRS} + ${CMAKE_CURRENT_SOURCE_DIR} +) +INCLUDE_DIRECTORIES(${HEADERS}) + +ADD_LIBRARY(${TARGET_NAME} STATIC ${SRCS}) + +SET_TARGET_PROPERTIES(${TARGET_NAME} PROPERTIES + COMPILE_FLAGS -fPIC + LINK_FLAGS "-Wl,--as-needed -Wl,--hash-style=both" +) + +SET_TARGET_PROPERTIES(${TARGET_NAME} + PROPERTIES + SOVERSION ${CMAKE_PROJECT_API_VERSION} + VERSION ${CMAKE_PROJECT_VERSION} +) + +TARGET_LINK_LIBRARIES(${TARGET_NAME} + ${${DEPS}_LDFLAGS} "-ldl" + ${${DEPS}_LIBRARIES} +) + +INSTALL(TARGETS ${TARGET_NAME} + DESTINATION lib + PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE + GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE +) + +GET_FILENAME_COMPONENT(CURRENT_DIR_NAME ${CMAKE_CURRENT_SOURCE_DIR} NAME) +INSTALL_FILE(IBoxPluginFactory.h include/${PROJECT_NAME}/${CURRENT_DIR_NAME}) +INSTALL_FILE(box_plugin_interface.h include/${PROJECT_NAME}/${CURRENT_DIR_NAME}) + +# openable plugins of web livebox +ADD_SUBDIRECTORY(AppBoxPlugin) diff --git a/src_mobile/Plugin/IBoxPluginConnector.h b/src_mobile/Plugin/IBoxPluginConnector.h new file mode 100644 index 0000000..3e94fb8 --- /dev/null +++ b/src_mobile/Plugin/IBoxPluginConnector.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file IBoxPluginConnector.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef I_BOX_PLUGIN_CONNECTOR_H +#define I_BOX_PLUGIN_CONNECTOR_H + +#include <memory> +#include <Core/BoxData.h> +#include <Core/Util/Noncopyable.h> +#include "box_plugin_interface.h" + +class IBoxPluginConnector: Noncopyable { + public: + virtual bool initialize() = 0; + virtual bool shutdown() = 0; + virtual bool requestCommand( + const request_cmd_type type, const BoxInfoPtr& boxInfo) = 0; + virtual std::string getBoxType(const std::string& serviceBoxId) = 0; + virtual ~IBoxPluginConnector() {}; +}; + +typedef std::shared_ptr<IBoxPluginConnector> IBoxPluginConnectorPtr; + +#endif // I_BOX_PLUGIN_CONNECTOR_H diff --git a/src_mobile/Plugin/IBoxPluginFactory.h b/src_mobile/Plugin/IBoxPluginFactory.h new file mode 100644 index 0000000..bbcb1ec --- /dev/null +++ b/src_mobile/Plugin/IBoxPluginFactory.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file IBoxPluginFactory.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef I_BOX_PLUGIN_FACTORY_H +#define I_BOX_PLUGIN_FACTORY_H + +#include <string> +#include <memory> +#include <Evas.h> +#include <ewk_context.h> + +// forward declaration +class IRenderView; +class IRenderBuffer; + +class IBoxPluginFactory { + public: + virtual std::shared_ptr<IRenderView> createRenderView( + std::string boxId, std::string instanceId, + std::shared_ptr<Ewk_Context> ewkContext) = 0; + + virtual std::shared_ptr<IRenderBuffer> createBoxRenderBuffer( + std::string boxId, std::string instanceId, + int width, int height, std::string data) = 0; + + virtual ~IBoxPluginFactory() {}; +}; + +typedef std::shared_ptr<IBoxPluginFactory> IBoxPluginFactoryPtr; + +#endif //I_BOX_PLUGIN_FACTORY_H diff --git a/src_mobile/Plugin/box_plugin_interface.h b/src_mobile/Plugin/box_plugin_interface.h new file mode 100644 index 0000000..9cc8a14 --- /dev/null +++ b/src_mobile/Plugin/box_plugin_interface.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file box_plugin_interface.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef BOX_PLUGIN_INTERFACE_H +#define BOX_PLUGIN_INTERFACE_H + +#include <string> +#include <Core/BoxData.h> + +#ifndef EXPORT_API +#define EXPORT_API __attribute__((visibility("default"))) +#endif + +#define WEB_PROVIDER_PLUGIN_INTERFACE_SYM_INITIALIZE "web_provider_plugin_interface_initialize" +#define WEB_PROVIDER_PLUGIN_INTERFACE_SYM_COMMAND "web_provider_plugin_interface_command" +#define WEB_PROVIDER_PLUGIN_INTERFACE_SYM_SHUTDOWN "web_provider_plugin_interface_shutdown" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + REQUEST_CMD_ADD_BOX, + REQUEST_CMD_REMOVE_BOX, + REQUEST_CMD_OPEN_PD, + REQUEST_CMD_CLOSE_PD, + REQUEST_CMD_RESIZE_BOX, + REQUEST_CMD_RESUME_BOX, + REQUEST_CMD_PAUSE_BOX, + REQUEST_CMD_RESUME_ALL, + REQUEST_CMD_PAUSE_ALL, + REQUEST_CMD_CHANGE_PERIOD, + REQUEST_CMD_UPDATE_BOX, + REQUEST_CMD_CHANGE_LANGUAGE +} request_cmd_type; + +// definition of interface function type +typedef int (*plugin_interface_func_initialize)(void); +typedef int (*plugin_interface_func_command)( + const request_cmd_type type, const BoxInfoPtr& boxInfo); +typedef int (*plugin_interface_func_shutdown)(void); + +typedef struct { + void* handle; + const char* service_boxid; + plugin_interface_func_initialize initialize; + plugin_interface_func_command command; + plugin_interface_func_shutdown shutdown; +} plugin_interfaces; + +// inteface functions that should be implemented by each plugin +EXPORT_API int web_provider_plugin_interface_initialize(); +EXPORT_API int web_provider_plugin_interface_command( + const request_cmd_type type, const BoxInfoPtr& boxInfo); +EXPORT_API int web_provider_plugin_interface_shutdown(); + +#ifdef __cplusplus +} +#endif + +#endif // BOX_PLUGIN_INTERFACE_H diff --git a/src_wearable/API/CMakeLists.txt b/src_wearable/API/CMakeLists.txt new file mode 100644 index 0000000..ae38767 --- /dev/null +++ b/src_wearable/API/CMakeLists.txt @@ -0,0 +1,72 @@ +# Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved +# +# Licensed under the Flora License, Version 1.1 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://floralicense.org/license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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) + +SET(TARGET_NAME ${TARGET_API}) +SET(DEPS ${TARGET_NAME}_DEPS) + +PKG_CHECK_MODULES(${DEPS} + db-util + glib-2.0 + json-glib-1.0 + dlog + capi-appfw-application + libsmack + REQUIRED +) +ADD_DEFINITIONS(${${DEPS}_CFLAGS}) + +SET(SRCS + ${CMAKE_CURRENT_SOURCE_DIR}/SqliteDB.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/web_provider_livebox_info.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/web_provider_plugin_info.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/web_provider_service.cpp +) + +SET(HEADERS + ${${DEPS}_INCLUDE_DIRS} + ${CMAKE_CURRENT_SOURCE_DIR} +) +INCLUDE_DIRECTORIES(${HEADERS}) + +ADD_LIBRARY(${TARGET_NAME} SHARED ${SRCS}) + +SET_TARGET_PROPERTIES(${TARGET_NAME} PROPERTIES + COMPILE_FLAGS -fPIC + LINK_FLAGS "-Wl,--as-needed -Wl,--hash-style=both" +) + +SET_TARGET_PROPERTIES(${TARGET_NAME} + PROPERTIES + SOVERSION ${CMAKE_PROJECT_API_VERSION} + VERSION ${CMAKE_PROJECT_VERSION} +) + +TARGET_LINK_LIBRARIES(${TARGET_NAME} + ${${DEPS}_LDFLAGS} "-ldl" + ${${DEPS}_LIBRARIES} +) + +INSTALL(TARGETS ${TARGET_NAME} + DESTINATION lib + PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE + GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE +) + +GET_FILENAME_COMPONENT(CURRENT_DIR_NAME ${CMAKE_CURRENT_SOURCE_DIR} NAME) +INSTALL_FILE(web-provider-info.h include/${PROJECT_NAME}/${CURRENT_DIR_NAME}) # Deprecated +INSTALL_FILE(web_provider_livebox_info.h include/${PROJECT_NAME}/${CURRENT_DIR_NAME}) +INSTALL_FILE(web_provider_plugin_info.h include/${PROJECT_NAME}/${CURRENT_DIR_NAME}) +INSTALL_FILE(web_provider_service.h include/${PROJECT_NAME}/${CURRENT_DIR_NAME}) diff --git a/src_wearable/API/SqliteDB.cpp b/src_wearable/API/SqliteDB.cpp new file mode 100644 index 0000000..32aa302 --- /dev/null +++ b/src_wearable/API/SqliteDB.cpp @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file SqliteDB.cpp + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#include <string> +#include <cstring> +#include <cstdarg> +#include <sqlite3.h> +#include <db-util.h> + +#include "SqliteDB.h" + +SqliteDB::SqliteDB(std::string dbPath) + : m_path(dbPath) + , m_handle(NULL) + , m_stmt(NULL) +{ +} + +SqliteDB::~SqliteDB() +{ +} + +bool SqliteDB::openDB() +{ + closeDB(); + int ret; + ret = db_util_open(m_path.c_str(), &m_handle, DB_UTIL_REGISTER_HOOK_METHOD); + if (ret != SQLITE_OK) { + return false; + } + + return true; +} + +void SqliteDB::closeDB() +{ + if (!m_handle) { + return; + } + + if (!m_stmt) { + db_util_close(m_handle); + m_handle = NULL; + return; + } + + sqlite3_finalize(m_stmt); + db_util_close(m_handle); + m_stmt = NULL; + m_handle = NULL; +} + +bool SqliteDB::setCommand(std::string& query, const char* fmt, ...) +{ + if (!m_handle || !fmt) { + return false; + } + + int ret = + sqlite3_prepare_v2(m_handle, query.c_str(), -1, &m_stmt, NULL); + + if (ret != SQLITE_OK) { + return false; + } + + // bind values to query + int intValue; + char* stringValue; + + va_list ap; + va_start(ap, fmt); + for (unsigned int i = 0; i < strlen(fmt); i++) { + switch (fmt[i]) { + case 'i': + intValue = va_arg(ap, int); + ret = sqlite3_bind_int(m_stmt, i + 1, intValue); + if (ret != SQLITE_OK) { + va_end(ap); + return false; + } + break; + case 's': + stringValue = va_arg(ap, char*); + ret = sqlite3_bind_text(m_stmt, i + 1, stringValue, -1, NULL); + if (ret != SQLITE_OK) { + va_end(ap); + return false; + } + break; + default: + break; + } + } + va_end(ap); + + return true; +} + +bool SqliteDB::executeCommand() +{ + int ret = sqlite3_step(m_stmt); + + if (ret != SQLITE_ROW) { + return false; + } + + return true; +} + +const char* SqliteDB::getText(int col) +{ + const char* ret = + reinterpret_cast<const char*>(sqlite3_column_text(m_stmt, col)); + + return ret; +} + +int SqliteDB::getInt(int col) +{ + return sqlite3_column_int(m_stmt, col); +} diff --git a/src_wearable/API/SqliteDB.h b/src_wearable/API/SqliteDB.h new file mode 100644 index 0000000..0f7c993 --- /dev/null +++ b/src_wearable/API/SqliteDB.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file SqliteDB.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef SQLITE_DB_H +#define SQLITE_DB_H + +#include <string> +#include <sqlite3.h> + +class SqliteDB { + public: + bool openDB(); + void closeDB(); + bool setCommand(std::string& query, const char* fmt, ...); + bool executeCommand(); + const char* getText(int col); + int getInt(int col); + + explicit SqliteDB(const std::string dbPath); + ~SqliteDB(); + + private: + std::string m_path; + sqlite3* m_handle; + sqlite3_stmt* m_stmt; +}; + +#endif // SQLITE_DB_H diff --git a/src_wearable/API/WebProviderDB.h b/src_wearable/API/WebProviderDB.h new file mode 100644 index 0000000..e6f14f6 --- /dev/null +++ b/src_wearable/API/WebProviderDB.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file WebProviderDB.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef LIVEBOX_DB_H +#define LIVEBOX_DB_H + +#include <string> +#include "SqliteDB.h" + +const std::string dbPath("/opt/usr/dbspace/.web_provider.db"); + +class WebProviderDB : public SqliteDB { + public: + WebProviderDB() : SqliteDB (dbPath) {}; + ~WebProviderDB() {}; +}; + +#endif //LIVEBOX_DB_H diff --git a/src_wearable/API/web-provider-info.h b/src_wearable/API/web-provider-info.h new file mode 100644 index 0000000..6d9a8b8 --- /dev/null +++ b/src_wearable/API/web-provider-info.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file web-provider-info.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef WEB_PROVIDER_INFO_H +#define WEB_PROVIDER_INFO_H + +#include <API/web_provider_livebox_info.h> + +#endif //WEB_PROVIDER_INFO_H diff --git a/src_wearable/API/web_provider_livebox_info.cpp b/src_wearable/API/web_provider_livebox_info.cpp new file mode 100644 index 0000000..6b0f0f3 --- /dev/null +++ b/src_wearable/API/web_provider_livebox_info.cpp @@ -0,0 +1,400 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file web_provider_livebox_info.cpp + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#include <cstring> +#include <memory> +#include <vector> +#include "WebProviderDB.h" +#include "web_provider_livebox_info.h" + +static const std::string infoTable("LiveboxInfo"); + +enum InfoTableField { + BOX_ID = 0, + APP_ID, + BOX_TYPE, + AUTO_LAUNCH, + MOUSE_EVENT, + PD_FAST_OPEN, +}; + +// TODO this default type should be retrieved more automatically +static const std::string defaultBoxType("app"); + +const char* web_provider_livebox_get_default_type() +{ + return defaultBoxType.c_str(); +} + +const char* web_provider_livebox_get_box_type(const char* box_id) +{ + if (!box_id) { + return NULL; + } + + std::shared_ptr<WebProviderDB> handle(new WebProviderDB()); + if (!handle->openDB()) { + return NULL; + } + + std::string query = "select * from " + infoTable + " where box_id = ?"; + if (!handle->setCommand(query, "s", box_id)) { + handle->closeDB(); + return NULL; + } + + if (!handle->executeCommand()) { + handle->closeDB(); + return NULL; + } + + const char* box_type = handle->getText(InfoTableField::BOX_TYPE); + const char* box_type_dup = NULL; + + if (box_type) { + box_type_dup = strdup(box_type); + } + + handle->closeDB(); + + return box_type_dup; +} + +const char* web_provider_livebox_get_app_id(const char* box_id) +{ + if (!box_id) { + return NULL; + } + + std::shared_ptr<WebProviderDB> handle(new WebProviderDB()); + if (!handle->openDB()) { + return NULL; + } + + std::string query = "select * from " + infoTable + " where box_id = ?"; + if (!handle->setCommand(query, "s", box_id)) { + handle->closeDB(); + return NULL; + } + + if (!handle->executeCommand()) { + handle->closeDB(); + return NULL; + } + + const char* app_id = handle->getText(InfoTableField::APP_ID); + const char* app_id_dup = NULL; + + if (app_id) { + app_id_dup = strdup(app_id); + } + + handle->closeDB(); + + return app_id_dup; +} + +int web_provider_livebox_get_auto_launch(const char* box_id) +{ + if (!box_id) { + return 0; + } + + std::shared_ptr<WebProviderDB> handle(new WebProviderDB()); + if (!handle->openDB()) { + return 0; + } + + std::string query = "select * from " + infoTable + " where box_id = ?"; + if (!handle->setCommand(query, "s", box_id)) { + handle->closeDB(); + return 0; + } + + if (!handle->executeCommand()) { + handle->closeDB(); + return 0; + } + + int autoLaunch = handle->getInt(InfoTableField::AUTO_LAUNCH); + handle->closeDB(); + + return autoLaunch; +} + +int web_provider_livebox_get_mouse_event(const char* box_id) +{ + if (!box_id) { + return 0; + } + + std::shared_ptr<WebProviderDB> handle(new WebProviderDB()); + if (!handle->openDB()) { + return 0; + } + + std::string query = "select * from " + infoTable + " where box_id = ?"; + if (!handle->setCommand(query, "s", box_id)) { + handle->closeDB(); + return 0; + } + + if (!handle->executeCommand()) { + handle->closeDB(); + return 0; + } + + int mouseEvent = handle->getInt(InfoTableField::MOUSE_EVENT); + handle->closeDB(); + + return mouseEvent; +} + +int web_provider_livebox_get_pd_fast_open(const char* box_id) +{ + if (!box_id) { + return 0; + } + + std::shared_ptr<WebProviderDB> handle(new WebProviderDB()); + if (!handle->openDB()) { + return 0; + } + + std::string query = "select * from " + infoTable + " where box_id = ?"; + if (!handle->setCommand(query, "s", box_id)) { + handle->closeDB(); + return 0; + } + + if (!handle->executeCommand()) { + handle->closeDB(); + return 0; + } + + int pdFastOpen = handle->getInt(InfoTableField::PD_FAST_OPEN); + handle->closeDB(); + + return pdFastOpen; +} + +int web_provider_livebox_insert_box_info( + const char* box_id, + const char* app_id, + const char* box_type, + int auto_launch, + int mouse_event, + int pd_fast_open) +{ + if (!box_id || !app_id || !box_type) { + return -1; + } + + std::shared_ptr<WebProviderDB> handle(new WebProviderDB()); + if (!handle->openDB()) { + return -1; + } + + std::string query = + "insert into " + infoTable + + " (box_id, app_id, box_type, auto_launch, mouse_event, pd_fast_open) \ + values (?,?,?,?,?,?)"; + + if (!handle->setCommand( + query, "sssiii", + box_id, app_id, box_type, auto_launch, mouse_event, pd_fast_open)) { + handle->closeDB(); + return -1; + } + + if (!handle->executeCommand()) { + handle->closeDB(); + return -1; + } + + handle->closeDB(); + return 0; +} + +int web_provider_livebox_delete_by_box_id(const char* box_id) +{ + if (!box_id) { + return -1; + } + + std::shared_ptr<WebProviderDB> handle(new WebProviderDB()); + if (!handle->openDB()) { + return -1; + } + + std::string query = + "delete from " + infoTable + " where box_id=?"; + + if (!handle->setCommand(query, "s", box_id)) { + handle->closeDB(); + return -1; + } + + if (!handle->executeCommand()) { + handle->closeDB(); + return -1; + } + + handle->closeDB(); + return 0; +} + +int web_provider_livebox_delete_by_app_id(const char* app_id) +{ + if (!app_id) { + return -1; + } + + std::shared_ptr<WebProviderDB> handle(new WebProviderDB()); + if (!handle->openDB()) { + return -1; + } + + std::string query = + "delete from " + infoTable + " where app_id=?"; + + if (!handle->setCommand(query, "s", app_id)) { + handle->closeDB(); + return -1; + } + + if (!handle->executeCommand()) { + handle->closeDB(); + return -1; + } + + handle->closeDB(); + return 0; +} + +int web_provider_livebox_delete_by_type(const char* type) +{ + if (!type) { + return -1; + } + + std::shared_ptr<WebProviderDB> handle(new WebProviderDB()); + if (!handle->openDB()) { + return -1; + } + + std::string query = + "delete from " + infoTable + " where type=?"; + + if (!handle->setCommand(query, "s", type)) { + handle->closeDB(); + return -1; + } + + if (!handle->executeCommand()) { + handle->closeDB(); + return -1; + } + + handle->closeDB(); + return 0; +} + +char** web_provider_livebox_get_box_id_list(const char* app_id, int* count) +{ + if (!app_id) { + return NULL; + } + + std::shared_ptr<WebProviderDB> handle(new WebProviderDB()); + if (!handle->openDB()) { + return NULL; + } + + std::string query = "select * from " + infoTable + " where app_id = ?"; + if (!handle->setCommand(query, "s", app_id)) { + handle->closeDB(); + return NULL; + } + + std::vector<char*> boxIdList; + while (handle->executeCommand()) { + const char* boxId = handle->getText(InfoTableField::BOX_ID); + boxIdList.push_back(strdup(boxId)); + } + + *count = boxIdList.size(); + if (*count == 0) { + handle->closeDB(); + return NULL; + } + + char** boxIds = static_cast<char**>(malloc((*count) * sizeof(char*))); + for (int i = 0; i < *count; i++) { + boxIds[i] = boxIdList[i]; + } + + handle->closeDB(); + return boxIds; +} + +void web_provider_livebox_release_box_id_list(char** box_id_list, int count) +{ + if (!box_id_list) { + return; + } + + for (int i = 0; i < count; i++) { + if (!box_id_list[i]) { + continue; + } + free(box_id_list[i]); + } +} + +int web_provider_livebox_check_box_installed(const char* box_id) +{ + if (!box_id) { + return 0; + } + + std::shared_ptr<WebProviderDB> handle(new WebProviderDB()); + if (!handle->openDB()) { + return 0; + } + + std::string query = "select * from " + infoTable + " where box_id = ?"; + if (!handle->setCommand(query, "s", box_id)) { + handle->closeDB(); + return 0; + } + + if (!handle->executeCommand()) { + handle->closeDB(); + return 0; + } + + int count = 0; + while (handle->executeCommand()) { + count++; + } + handle->closeDB(); + + return count ? 1 : 0; +} diff --git a/src_wearable/API/web_provider_livebox_info.h b/src_wearable/API/web_provider_livebox_info.h new file mode 100644 index 0000000..e170f88 --- /dev/null +++ b/src_wearable/API/web_provider_livebox_info.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file web_provider_livebox_info.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef WEB_PROVIDER_LIVEBOX_INFO_H +#define WEB_PROVIDER_LIVEBOX_INFO_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef EXPORT_API +#define EXPORT_API __attribute__((visibility("default"))) +#endif + +#define DEPRECATED_API __attribute__((visibility("default"))) __attribute__((deprecated)) + +/* TODO doxygen comments are needed to each exported API */ + +EXPORT_API const char* web_provider_livebox_get_default_type(); +EXPORT_API const char* web_provider_livebox_get_box_type(const char* box_id); +EXPORT_API const char* web_provider_livebox_get_app_id(const char* box_id); +EXPORT_API int web_provider_livebox_get_auto_launch(const char* box_id); +EXPORT_API int web_provider_livebox_get_mouse_event(const char* box_id); +EXPORT_API int web_provider_livebox_get_pd_fast_open(const char* box_id); +EXPORT_API int web_provider_livebox_insert_box_info( + const char* box_id, + const char* app_id, + const char* box_type, + int auto_launch, + int mouse_event, + int pd_fast_open); +EXPORT_API int web_provider_livebox_delete_by_box_id(const char* box_id); +EXPORT_API int web_provider_livebox_delete_by_app_id(const char* app_id); +EXPORT_API int web_provider_livebox_delete_by_type(const char* type); + +EXPORT_API char** web_provider_livebox_get_box_id_list(const char* app_id, int* count); +EXPORT_API void web_provider_livebox_release_box_id_list(char** box_id_list, int count); +EXPORT_API int web_provider_livebox_check_box_installed(const char* box_id); + +#ifdef __cplusplus +} +#endif +#endif //WEB_PROVIDER_LIVEBOX_INFO_H diff --git a/src_wearable/API/web_provider_plugin_info.cpp b/src_wearable/API/web_provider_plugin_info.cpp new file mode 100755 index 0000000..dae4588 --- /dev/null +++ b/src_wearable/API/web_provider_plugin_info.cpp @@ -0,0 +1,349 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file web_provider_livebox_info.cpp + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ + + +#include <sys/stat.h> +#include <sys/types.h> +#include <dirent.h> +#include <string> +#include <cstring> +#include <cstdlib> +#include <list> +#include <glib.h> +#include <glib-object.h> +#include <json-glib/json-glib.h> +#include <Core/Util/Log.h> +#include "web_provider_livebox_info.h" +#include "web_provider_plugin_info.h" +#include <memory> + +// static functions +static web_provider_plugin_info* get_parsed_json_data(std::string& configPath); +static bool web_provider_plugin_release_info(web_provider_plugin_info* info); + +static const std::string installedPluginDirPath("/usr/lib/web-provider/"); + +// Json's content for plugin is the following (example) +// { +// "type" : "clip", +// "path" : "/usr/lib/web-provider/libweb-provider-plugin-clipbox.so", +// "service_boxid" : "org.tizen.browser" +// } +// +// "service_boxid" is only optional member in json file + +static const std::string jsonMemberType("type"); +static const std::string jsonMemberPath("path"); +static const std::string jsonMemberBoxId("service_boxid"); +static const std::string jsonMemberBoxScrollable("box_scrollable"); +static const std::string jsonMemberBoxSize("supported_size"); + +static const std::string jsonValueBoolTrue("true"); +static const std::string jsonValueBoolFalse("false"); +static const std::string jsonFileExtension(".json"); +static const std::string mandatoryBoxSize("1x1"); + +web_provider_plugin_info** web_provider_plugin_get_installed_list(int* count) +{ + LogD("enter"); + + // open directory of web provider plugin + DIR* dir = opendir(installedPluginDirPath.c_str()); + if (!dir) { + LogD("failed to open directory for web livebox plugins"); + *count = 0; + return NULL; + } + + // read plugin directory and store plugin config path + std::list<std::string> configList; + struct dirent* entry; + struct stat configStat; + std::string configPath; + while ((entry = readdir(dir))) { + if ((!strcmp(entry->d_name, ".")) || (!strcmp(entry->d_name, ".."))) { + continue; + } + + configPath = installedPluginDirPath + entry->d_name; + + if (stat(configPath.c_str(), &configStat) < 0) { + LogD("Failed to open file"); + continue; + } + + if (S_ISDIR(configStat.st_mode)) { + continue; + } + + if (configPath.substr(configPath.find_last_of(".")) == jsonFileExtension) { + LogD("config file: %s", configPath.c_str()); + configList.push_back(configPath); + } + } + // close directory of web provider plugin + closedir(dir); + + if (configList.size() == 0) { + *count = 0; + return NULL; + } + + // parse available each plugin json file + std::list<web_provider_plugin_info*> pluginList; + for (auto it = configList.begin(); + it != configList.end(); it++) { + web_provider_plugin_info* info = get_parsed_json_data(*it) ; + if (!info) { + continue; + } + + pluginList.push_back(info); + } + *count = pluginList.size(); + LogD("read plugin count: %d", *count); + + // c style array allocation for return of result + web_provider_plugin_info** info_list = + static_cast<web_provider_plugin_info**>( + malloc((*count) * sizeof(web_provider_plugin_info*))); + + // copy from members in std::list to one in c style array + int idx = 0; + for (auto it = pluginList.begin(); + it != pluginList.end(); it++) { + LogD("type: %s", (*it)->type); + LogD("path: %s", (*it)->path); + if ((*it)->service_boxid) { + LogD("service_boxid: %s", (*it)->service_boxid); + } + info_list[idx] = *it; + idx++; + } + + LogD("success to return plugin information"); + return info_list; +} + +void web_provider_plugin_release_installed_list( + web_provider_plugin_info** info_list, + int count) +{ + if (!info_list) { + return; + } + + for (int i = 0; i < count; i++) { + web_provider_plugin_release_info(info_list[i]); + } +} + +int web_provider_plugin_get_box_scrollable(const char* plugin_type) +{ + if (!plugin_type) { + return -1; + } + + std::string configPath; + configPath = installedPluginDirPath; + configPath += plugin_type; + configPath += jsonFileExtension; + web_provider_plugin_info* info = get_parsed_json_data(configPath); + + if (!info) { + return -1; + } + int ret = info->box_scrollable; + web_provider_plugin_release_info(info); + + LogD("box_scrollable: %d", ret); + return ret; +} + +static web_provider_plugin_info* get_parsed_json_data(std::string& configPath) +{ + g_type_init(); + + web_provider_plugin_info* info; + JsonParser* parser = json_parser_new(); + GError* error = NULL; + + if (!json_parser_load_from_file(parser, configPath.c_str(), &error)) { + LogD("failed to parse json file: %s -> %s", configPath.c_str(), error->message); + g_error_free(error); + g_object_unref(parser); + return NULL; + } + + JsonNode* root = json_parser_get_root(parser); + JsonObject* object = json_node_get_object(root); + + // check if type member exists on this json file + const char* type = + static_cast<const char*>( + json_object_get_string_member(object, jsonMemberType.c_str())); + + const char* path = + static_cast<const char*>( + json_object_get_string_member(object, jsonMemberPath.c_str())); + + JsonArray* size = + json_object_get_array_member(object, jsonMemberBoxSize.c_str()); + int sizeCount = static_cast<int>(json_array_get_length(size)); + + if (!type || !path || !sizeCount) { + LogD("mandatory members don't exist"); + g_error_free(error); + g_object_unref(parser); + return NULL; + } + + // allocate instance of plugin info struct + info = static_cast<web_provider_plugin_info*>( + malloc(sizeof(web_provider_plugin_info))); + memset(info, 0, sizeof(web_provider_plugin_info)); + + info->type = strdup(type); + info->path = strdup(path); + info->box_size = static_cast<char**>(malloc(sizeof(char*) * sizeCount)); + + for (int i = 0; i < sizeCount; i++) { + info->box_size[i] = + strdup(static_cast<const char*>(json_array_get_string_element(size, i))); + } + info->box_size_count = sizeCount; + + gboolean hasBoxId = json_object_has_member(object, jsonMemberBoxId.c_str()); + if (hasBoxId == TRUE) { + const char* boxId = + static_cast<const char*>( + json_object_get_string_member(object, jsonMemberBoxId.c_str())); + if (boxId) { + info->service_boxid = strdup(boxId); + } + } + + gboolean hasBoxScrollable = + json_object_has_member(object, jsonMemberBoxScrollable.c_str()); + if (hasBoxScrollable == TRUE) { + const char* boxScrollable = + static_cast<const char*>( + json_object_get_string_member(object, jsonMemberBoxScrollable.c_str())); + if (boxScrollable && (jsonValueBoolTrue == boxScrollable)) { + info->box_scrollable = 1; + } else { + info->box_scrollable = 0; + } + } + + LogD("type: %s", info->type); + LogD("path: %s", info->path); + if (info->service_boxid) { + LogD("service_boxid: %s", info->service_boxid); + } + LogD("box_scrollable: %d", info->box_scrollable); + + g_error_free(error); + g_object_unref(parser); + + return info; +} + +bool web_provider_plugin_release_info(web_provider_plugin_info* info) +{ + LogD("enter"); + if (!info) { + LogD("empty struct"); + return false; + } + + // only members with buffer are released + delete info->type; + delete info->path; + delete info->service_boxid; + for(int i = 0; i < info->box_size_count; i++) { + delete[] info->box_size[i]; + } + delete info; + + return true; +} + +int web_provider_plugin_check_supported_size( + const char* plugin_type, char** size, int sizeCount) +{ + // read plugin directory and store plugin config path + std::string configPath; + configPath = installedPluginDirPath; + configPath += plugin_type; + configPath += jsonFileExtension; + + // get the json datas + web_provider_plugin_info* jsonData = get_parsed_json_data(configPath); + if (!jsonData) { + LogD("failed to get the json file"); + return false; + } + + // check if this type is default type + bool isDefaultType = false; + const char* defaultType = web_provider_livebox_get_default_type(); + if (!defaultType) { + LogD("can't get default type"); + return false; + } + if (!strcmp(plugin_type, defaultType)) { + isDefaultType = true; + } + + // compare the parsed config data with the parsed json data + bool mandatoryCheck = false; + for (int configCnt = 0; configCnt < sizeCount; configCnt++) { + bool supportedSizeCheck = false; + for (int jsonCnt = 0; jsonCnt < jsonData->box_size_count; jsonCnt++) { + + // check mandatory size + if (isDefaultType && !strcmp(mandatoryBoxSize.c_str(), size[configCnt])) { + mandatoryCheck = true; + } + + // check supported size + if (!strcmp(jsonData->box_size[jsonCnt], size[configCnt])) { + supportedSizeCheck = true; + break; + } + } + + if (!supportedSizeCheck) { + LogD("Not supported size: %s", size[configCnt]); + web_provider_plugin_release_info(jsonData); + return false; + } + } + + //release the jsonData + web_provider_plugin_release_info(jsonData); + if (isDefaultType && !mandatoryCheck) { + LogD("Mandatory members don't exist "); + return false; + } + + return true; +} diff --git a/src_wearable/API/web_provider_plugin_info.h b/src_wearable/API/web_provider_plugin_info.h new file mode 100755 index 0000000..612497c --- /dev/null +++ b/src_wearable/API/web_provider_plugin_info.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file web_provider_plugin_info.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef WEB_PROVIDER_PLUGIN_INFO_H +#define WEB_PROVIDER_PLUGIN_INFO_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef EXPORT_API +#define EXPORT_API __attribute__((visibility("default"))) +#endif + +struct _web_provider_plugin_info { + const char* type; + const char* path; + const char* service_boxid; + char** box_size; + int box_scrollable; + int box_size_count; +}; +typedef _web_provider_plugin_info web_provider_plugin_info; + +EXPORT_API web_provider_plugin_info** web_provider_plugin_get_installed_list( + int* count); +EXPORT_API void web_provider_plugin_release_installed_list( + web_provider_plugin_info** info_list, + int count); +EXPORT_API int web_provider_plugin_get_box_scrollable(const char* plugin_type); +EXPORT_API int web_provider_plugin_check_supported_size(const char* plugin_type, char** size, int sizeCount); +#ifdef __cplusplus +} +#endif +#endif //WEB_PROVIDER_PROVIDER_INFO_H diff --git a/src_wearable/API/web_provider_service.cpp b/src_wearable/API/web_provider_service.cpp new file mode 100644 index 0000000..639e1bc --- /dev/null +++ b/src_wearable/API/web_provider_service.cpp @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file web_provider_service.cpp + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ + +#include <fcntl.h> +#include <string> +#include <sstream> +#include <sys/epoll.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/smack.h> +#include <string.h> +#include <unistd.h> +#include <app_service.h> + +#include "web_provider_livebox_info.h" +#include "web_provider_service.h" + +static std::string getFifoFile(const char* appId) +{ + int boxCount = 0; + char** boxList = web_provider_livebox_get_box_id_list(appId, &boxCount); + if (!boxList) { + return std::string(); + } + web_provider_livebox_release_box_id_list(boxList, boxCount); + + std::string fifoFile = "/tmp/"; + fifoFile += appId; + + return fifoFile; +} + +static bool requestRemoveBoxesByAppId(const char* appId) +{ + if (!appId) { + return false; + } + + service_h handle = NULL; + int ret = SERVICE_ERROR_NONE; + + ret = service_create(&handle); + if (ret != SERVICE_ERROR_NONE && !handle) { + return false; + } + + ret = service_set_package(handle, SERVICE_WEB_PROVIDER_APPID); + if (ret != SERVICE_ERROR_NONE) { + service_destroy(handle); + return false; + } + + ret = service_set_operation(handle, SERVICE_OPERATION_BOX_REMOVE); + if (ret != SERVICE_ERROR_NONE) { + service_destroy(handle); + return false; + } + + // set special key as extra data for removing boxes by web-provider + service_add_extra_data(handle, SERVICE_REMOVE_APPID_KEY, appId); + + ret = service_send_launch_request(handle, NULL, NULL); + if (ret != SERVICE_ERROR_NONE) { + service_destroy(handle); + return false; + } + + service_destroy(handle); + return true; +} + +int web_provider_service_wait_boxes_removed(const char* app_id) +{ + if (!app_id) { + return -1; + } + + // 1. request service for removing boxes to web-provider + // 2. wait using epoll_wait while fifo file is changed + if(!requestRemoveBoxesByAppId(app_id)) { + return -1; + } + + // create fifo file + std::string fifoFile = getFifoFile(app_id); + int ret = mkfifo(fifoFile.c_str(), 0666); + if (ret < 0) { + if (errno != EEXIST) { + return -1; + } + } + chown(fifoFile.c_str(), 5000, 5000); + ret = smack_setlabel(fifoFile.c_str(), "*", SMACK_LABEL_ACCESS); + if (ret < 0) { + return -1; + } + + int epollMaxSize = 1; + int epollFd = epoll_create(epollMaxSize); + int fifoFd = open(fifoFile.c_str(), O_RDONLY | O_NONBLOCK); + if (fifoFd < 0) { + return -1; + } + + struct epoll_event fifoEvent; + fifoEvent.events = EPOLLIN | EPOLLOUT; + fifoEvent.data.fd = fifoFd; + + struct epoll_event events; + if (epoll_ctl(epollFd, EPOLL_CTL_ADD, fifoFd, &fifoEvent) < 0) { + close(fifoFd); + return -1; + } + + int epollTimeOut = 10000; // 10 seconds + int status = epoll_wait(epollFd, &events, epollMaxSize, epollTimeOut); + // epoll is unblocked! + + int result = 0; + if (status < 0) { + // epoll failed + } else if (status == 0) { + // epoll timeout + } else { + int buffMaxSize = 2; + char buff[buffMaxSize]; + memset(buff, 0x0, buffMaxSize); + int size = read(fifoFd, buff, buffMaxSize); + if (size > 0) { + std::string status(buff); + std::istringstream inputStream(status); + inputStream >> result; + } + } + + close(fifoFd); + close(epollFd); + unlink(fifoFile.c_str()); + return result; +} + +int web_provider_service_wakeup_installer(const char* app_id) +{ + if (!app_id) { + return -1; + } + + std::string fifoFile = getFifoFile(app_id); + int fifoFd = open(fifoFile.c_str(), O_WRONLY | O_NONBLOCK); + if (fifoFd < 0) { + return -1; + } + + std::string result("1"); + write(fifoFd, result.c_str(), result.size() + 1); + close(fifoFd); + return 0; +} diff --git a/src_wearable/API/web_provider_service.h b/src_wearable/API/web_provider_service.h new file mode 100644 index 0000000..9dc3e21 --- /dev/null +++ b/src_wearable/API/web_provider_service.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file web_provider_service.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef WEB_PROVIDER_SERVICE_H +#define WEB_PROVIDER_SERVICE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef EXPORT_API +#define EXPORT_API __attribute__((visibility("default"))) +#endif + +// These are string for removing dboxes from wrt-installer +#define SERVICE_OPERATION_BOX_REMOVE "http://tizen.org/appcontrol/operation/dynamicbox/web/remove" +#define SERVICE_WEB_PROVIDER_APPID "dbox.web-provider" +#define SERVICE_REMOVE_APPID_KEY "app_id" + +// These are string for updating dboxes from web app +#define SERVICE_OPERATION_BOX_UPDATE "http://tizen.org/appcontrol/operation/dynamicbox/web/update" +#define SERVICE_BOX_SERVICE_SCHEME "box-service://" +#define SERVICE_CONTENT_INFO_KEY "content-info" +#define SERVICE_ALARM_CALLER_KEY "__ALARM_MGR_CALLER_APPID" + +EXPORT_API int web_provider_service_wait_boxes_removed(const char* app_id); +EXPORT_API int web_provider_service_wakeup_installer(const char* app_id); + +#ifdef __cplusplus +} +#endif +#endif //WEB_PROVIDER_SERVICE_H diff --git a/src_wearable/CMakeLists.txt b/src_wearable/CMakeLists.txt new file mode 100644 index 0000000..0a978b0 --- /dev/null +++ b/src_wearable/CMakeLists.txt @@ -0,0 +1,31 @@ +# Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved +# +# Licensed under the Flora License, Version 1.1 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://floralicense.org/license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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) + +SET(TARGET_API web-provider-api) +SET(TARGET_CORE web-provider-core) +SET(TARGET_DAEMON web-provider) +SET(TARGET_PLUGIN web-provider-plugin) + +INCLUDE_DIRECTORIES( + ${CMAKE_CURRENT_SOURCE_DIR}/API + ${CMAKE_CURRENT_SOURCE_DIR}/Core + ${CMAKE_CURRENT_SOURCE_DIR}/Plugin +) + +ADD_SUBDIRECTORY(API) +ADD_SUBDIRECTORY(Core) +ADD_SUBDIRECTORY(Daemon) +ADD_SUBDIRECTORY(Plugin) diff --git a/src_wearable/Core/Box.cpp b/src_wearable/Core/Box.cpp new file mode 100644 index 0000000..84aaf6f --- /dev/null +++ b/src_wearable/Core/Box.cpp @@ -0,0 +1,311 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file Box.cpp + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#include <sstream> +#include <Ecore.h> +#include <Plugin/IBoxPluginFactory.h> +#include "Util/Log.h" +#include "Util/Util.h" +#include "BoxData.h" +#include "IBoxState.h" +#include "BoxState.h" +#include "Util/ITimer.h" +#include "BoxUpdateTimer.h" +#include "Box.h" + +Box::Box(BoxInfoPtr boxInfo, IBoxPluginFactoryPtr factory, EwkContextPtr ewkContext) + : m_boxInfo(boxInfo) + , m_factory(factory) + , m_currentTab(true) + , m_paused(false) + , m_updateNeeded(false) + , m_remainUpdateRequestTime() + , m_showed(false) +{ + LogD("enter"); + try { + m_renderView = m_factory->createRenderView(m_boxInfo, ewkContext); + m_updateTimer = BoxUpdateTimer::create( + boxInfo->period, Box::updateCallback, this); + // TODO code regarding state needs more testing + //m_state = BoxInitState::create( + // IBoxContextPtr(dynamic_cast<IBoxContext*>(this))); + } catch (...) { + throw; + } +} + +Box::~Box() +{ + LogD("enter"); +} + +bool Box::show() +{ + LogD("enter"); + CHECK_BOX_STATE(m_state, permitShow); + + try { + m_updateTimer->start(); + m_renderView->show(); + } catch (...) { + return false; + } + m_showed = true; + SWITCH_BOX_STATE(); + return true; +} + +bool Box::hide() +{ + LogD("enter"); + CHECK_BOX_STATE(m_state, permitHide); + + try { + m_updateTimer->stop(); + m_renderView->hide(); + } catch (...) { + return false; + } + + SWITCH_BOX_STATE(); + return true; +} + +bool Box::resize(int width, int height) +{ + LogD("enter"); + CHECK_BOX_STATE(m_state, permitShow); + + // reset box info to new width, height + m_boxInfo->boxWidth = width; + m_boxInfo->boxHeight = height; + + try { + m_updateTimer->restart(); + m_renderView->resize(); + } catch (...) { + LogD("resize exception"); + return false; + } + m_showed = true; + SWITCH_BOX_STATE(); + return true; +} + +bool Box::resume() +{ + LogD("enter"); + CHECK_BOX_STATE(m_state, permitResume); + + try { + m_currentTab = true; + m_paused = false; + + if (m_updateTimer->getPeriod() > 0) { + // check for need updateTimer + time_t currentTime = time(NULL); + float diffTime = static_cast<float>(difftime(currentTime, m_remainUpdateRequestTime)); + if (diffTime < m_updateTimer->getPeriod()) { + if (!m_updateTimer->isRunning()) { + // we need start timer only remained time from first timer launched + m_updateTimer->continueTimer(m_updateTimer->getPeriod() - diffTime); + } + } else { + m_updateNeeded = true; + } + } + + if (m_updateNeeded) { + m_updateNeeded = false; + m_updateTimer->start(); + m_renderView->update(); + } else { + m_renderView->resume(); + } + } catch (...) { + return false; + } + m_showed = true; + SWITCH_BOX_STATE(); + return true; +} + +bool Box::needToUpdate() +{ + LogD("enter"); + if (m_updateTimer && m_updateTimer->getPeriod() > 0) { + // check for need updateTimer + time_t currentTime = time(NULL); + float diffTime = static_cast<float>(difftime(currentTime, m_remainUpdateRequestTime)); + if (diffTime >= m_updateTimer->getPeriod()) { + LogD("enter"); + return true; + } + + if (m_updateNeeded) { + return true; + } + return false; + } + + if (!m_showed || m_updateNeeded) { + return true; + } + + return false; +} + +bool Box::pause(bool background) +{ + LogD("enter"); + CHECK_BOX_STATE(m_state, permitPause); + + try { + if (!background) { + m_currentTab = false; + } + m_paused = true; + m_renderView->pause(); + + if (m_updateTimer->isRunning()) { + m_remainUpdateRequestTime = m_updateTimer->getStartTime(); + m_updateTimer->stop(); + } + } catch (...) { + return false; + } + + SWITCH_BOX_STATE(); + return true; +} + +bool Box::openPd(int width, int height, double x, double y) +{ + LogD("enter"); + CHECK_BOX_STATE(m_state, permitOpenPd); + + m_boxInfo->pdWidth = width; + m_boxInfo->pdHeight = height; + m_boxInfo->pdX = x; + m_boxInfo->pdY = y; + + try { + m_updateTimer->stop(); + m_renderView->openPd(); + } catch (...) { + return false; + } + m_showed = true; + SWITCH_BOX_STATE(); + return true; +} + +bool Box::closePd() +{ + LogD("enter"); + CHECK_BOX_STATE(m_state, permitClosePd); + + try { + m_renderView->closePd(); + m_updateTimer->restart(); + } catch (...) { + return false; + } + + SWITCH_BOX_STATE(); + return true; +} + +bool Box::update(std::string& appContentInfo) +{ + LogD("enter"); + + m_boxInfo->appContentInfo = appContentInfo; + if (m_paused) { + // update is dalayed + m_updateNeeded = true; + return true; + } + + try { + m_updateTimer->start(); + m_renderView->update(); + } catch (...) { + return false; + } + m_showed = true; + return true; +} + +bool Box::changePeriod(float period) +{ + LogD("enter"); + + // reset period + m_boxInfo->period = period; + + if (m_updateTimer->isRunning()) { + m_updateTimer->setPeriod(m_boxInfo->period); + } + + return true; +} + +bool Box::isCurrentTab() +{ + return m_currentTab; +} + +void Box::setState(IBoxStatePtr state) +{ + UNUSED_PARAM(state); + // assign new state + //m_state = state; +} + +Eina_Bool Box::updateCallback(void* data) +{ + LogD("enter"); + Box* This = static_cast<Box*>(data); + This->update(This->m_boxInfo->appContentInfo); + return ECORE_CALLBACK_RENEW; +} + +BoxInfoPtr Box::getBoxInfo() +{ + LogD("enter"); + return m_boxInfo; +} + +void Box::setNeedToUpdate() +{ + m_updateNeeded = true; +} + +bool Box::isPaused() +{ + return m_paused; +} + +void Box::setCurrent() +{ + m_currentTab = true; + m_paused = false; +} diff --git a/src_wearable/Core/Box.h b/src_wearable/Core/Box.h new file mode 100644 index 0000000..1ad7fda --- /dev/null +++ b/src_wearable/Core/Box.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file Box.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef BOX_H +#define BOX_H + +#include <string> +#include <memory> +#include <ctime> +#include <Ecore.h> +#include <Plugin/IBoxPluginFactory.h> +#include "Buffer/IRenderBuffer.h" +#include "View/IRenderView.h" +#include "Util/ITimer.h" +#include "BoxData.h" +#include "IBoxState.h" +#include "IBoxContext.h" +#include "IBox.h" +#include "Box.h" + +class Box: public IBox, public IBoxContext { + public: + static IBoxPtr create( + BoxInfoPtr boxInfo, + IBoxPluginFactoryPtr factory, + EwkContextPtr ewkContext) + { + return IBoxPtr(new Box(boxInfo, factory, ewkContext)); + }; + // IBox + bool show(); + bool hide(); + bool resize(int width, int height); + bool resume(); + bool pause(bool background); + bool openPd(int width, int height, double x, double y); + bool closePd(); + bool update(std::string& contentInfo); + bool changePeriod(float period); + bool isCurrentTab(); + bool needToUpdate(); + void setNeedToUpdate(); + void setCurrent(); + bool isPaused(); + BoxInfoPtr getBoxInfo(); + + ~Box(); + + private: + // IBoxContext + void setState(IBoxStatePtr state); + + // static callbacks + static Eina_Bool updateCallback(void* data); + + // constructor + explicit Box( + BoxInfoPtr boxInfo, + IBoxPluginFactoryPtr factory, + EwkContextPtr ewkContext); + + BoxInfoPtr m_boxInfo; + IBoxPluginFactoryPtr m_factory; + IRenderViewPtr m_renderView; + ITimerPtr m_updateTimer; + //IBoxStatePtr m_state; + // flag for knowing this box is on current tab + bool m_currentTab; + // flag for knowing this box has been already paused + bool m_paused; + // flag for knowing this box should be updated when the box is resumed + bool m_updateNeeded; + // timestamp for updateTimer + time_t m_remainUpdateRequestTime; + bool m_showed; +}; + +#endif //BOX_H diff --git a/src_wearable/Core/BoxData.h b/src_wearable/Core/BoxData.h new file mode 100644 index 0000000..123e737 --- /dev/null +++ b/src_wearable/Core/BoxData.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file BoxData.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef BOX_DATA_H +#define BOX_DATA_H + +#include <memory> +#include <string> + +struct BoxInfo +{ + std::string boxType; + std::string boxId; + std::string instanceId; + int boxWidth; + int boxHeight; + int pdWidth; + int pdHeight; + double pdX; + double pdY; + int priority; + float period; + // contentInfo is used differently per box type + std::string contentInfo; + // appContentInfo is used for saving custom data from box's app + std::string appContentInfo; + + // initialization + BoxInfo(std::string boxType, + std::string boxId, + std::string instanceId) : + boxType(boxType), + boxId(boxId), + instanceId(instanceId), + boxWidth(0), + boxHeight(0), + pdWidth(0), + pdHeight(0), + pdX(0.0f), + pdY(0.0f), + priority(0), + period(0), + contentInfo(), + appContentInfo() + { + }; + + BoxInfo() : + boxType(), + boxId(), + instanceId(), + boxWidth(0), + boxHeight(0), + pdWidth(0), + pdHeight(0), + pdX(0.0f), + pdY(0.0f), + priority(0), + period(0), + contentInfo(), + appContentInfo() + { + }; +}; + +typedef std::shared_ptr<struct BoxInfo> BoxInfoPtr; +typedef struct BoxInfo& BoxInfoRef; + +#endif // BOX_DATA_H diff --git a/src_wearable/Core/BoxLoadBalancer.cpp b/src_wearable/Core/BoxLoadBalancer.cpp new file mode 100755 index 0000000..e382df7 --- /dev/null +++ b/src_wearable/Core/BoxLoadBalancer.cpp @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file BoxLoadBalancer.cpp + * @author Minhyung Ko (minhyung.ko@samsung.com) + */ +#include "Util/Log.h" +#include "Util/Util.h" +#include "BoxLoadBalancer.h" + +// boxLoadBalanceTimer period +#define BOX_UPDATE_TIME 0.1 +#define BOX_UPDATE_TIME_INC 0.3 +#define BOX_UPDATE_MAX_TIME 5.0f +#define BOX_UPDATE_QUEUE_SIZE_THRESHOLD 5 + +BoxAsyncCommandInfo::BoxAsyncCommandInfo(request_box_cmd_type type, IBoxPtr boxPtr, BoxInfoPtr boxInfoPtr) +{ + m_type = type; + m_box = boxPtr; + m_boxInfo = boxInfoPtr; +} + +BoxAsyncCommandInfo::BoxAsyncCommandInfo(request_box_cmd_type type, IBoxPtr boxPtr, std::string& appContentInfo) +{ + m_type = type; + m_box = boxPtr; + m_appContentInfo = appContentInfo; +} + +BoxLoadBalancer::BoxLoadBalancer() +{ + m_vecBoxAsyncCommandList.clear(); + m_boxLoadBalanceTimer = NULL; + m_updateTimeCount = 0.0f; +} + +BoxLoadBalancer::~BoxLoadBalancer() +{ + +} + +Eina_Bool BoxLoadBalancer::requestBoxLoadBalanceCallback(void* data) +{ + LogD("requestBoxLoadBalanceCallback"); + BoxLoadBalancer* This = static_cast<BoxLoadBalancer*>(data); + + if (This->m_vecBoxAsyncCommandList.empty()) { + LogD("m_vecBoxAsyncCommandList.size() is empty"); + This->m_boxLoadBalanceTimer = NULL; + return ECORE_CALLBACK_CANCEL; + } + + BoxAsyncCommandInfoPtr boxCommandPtr = This->m_vecBoxAsyncCommandList.front(); + + switch (boxCommandPtr->getType()) { + case BOX_AYNC_REQUEST_CMD_SHOW: + boxCommandPtr->getBoxPtr()->show(); + break; + case BOX_AYNC_REQUEST_CMD_RESUME: + boxCommandPtr->getBoxPtr()->resume(); + break; + case BOX_AYNC_REQUEST_CMD_UPDATE: + { + std::string contentInfo = boxCommandPtr->getAppContentInfo(); + boxCommandPtr->getBoxPtr()->update(contentInfo); + break; + } + default: + LogW("Wrong command %d", boxCommandPtr->getType()); + } + + This->m_vecBoxAsyncCommandList.erase(This->m_vecBoxAsyncCommandList.begin()); + int commandListNumber = This->m_vecBoxAsyncCommandList.size(); + + if (commandListNumber > BOX_UPDATE_QUEUE_SIZE_THRESHOLD) { + float timecountbefore = BOX_UPDATE_TIME + BOX_UPDATE_TIME_INC * (commandListNumber - BOX_UPDATE_QUEUE_SIZE_THRESHOLD); + + if (timecountbefore > BOX_UPDATE_MAX_TIME) { + timecountbefore = BOX_UPDATE_MAX_TIME; + } + ecore_timer_del(This->m_boxLoadBalanceTimer); + + This->m_updateTimeCount = timecountbefore; + + This->m_boxLoadBalanceTimer = ecore_timer_add( This->m_updateTimeCount, requestBoxLoadBalanceCallback, This); + LogD("requestBoxLoadBalanceCallback launched pending until %f m_updateTimeCount %d size", This->m_updateTimeCount, commandListNumber); + return ECORE_CALLBACK_CANCEL; + } + + if (commandListNumber > 0 && (This->m_updateTimeCount > BOX_UPDATE_TIME)) { + ecore_timer_del(This->m_boxLoadBalanceTimer); + This->m_updateTimeCount = BOX_UPDATE_TIME; + This->m_boxLoadBalanceTimer = ecore_timer_add( This->m_updateTimeCount, requestBoxLoadBalanceCallback, This); + } + + if (commandListNumber > 0) { + LogD("m_vecBoxAsyncCommandList.size() = %d", commandListNumber); + return ECORE_CALLBACK_RENEW; + } + + This->m_boxLoadBalanceTimer = NULL; + + return ECORE_CALLBACK_CANCEL; +} + +void BoxLoadBalancer::eraseBoxAsyncCommandFromQueue(IBoxPtr boxPtr) +{ + if (!m_vecBoxAsyncCommandList.empty()) { + for (std::vector<BoxAsyncCommandInfoPtr>::iterator it = m_vecBoxAsyncCommandList.begin(); + it != m_vecBoxAsyncCommandList.end(); it++) { + BoxAsyncCommandInfoPtr boxCommandPtr = *it; + if ( boxCommandPtr->getBoxPtr() == boxPtr) { + m_vecBoxAsyncCommandList.erase(it); + LogD("m_vecBoxAsyncCommandList.erase"); + return; + } + } + } +} + +void BoxLoadBalancer::pushBoxAsyncCommandIntoQueue(request_box_cmd_type cmdType, IBoxPtr boxPtr, BoxInfoPtr boxInfoPtr) +{ + BoxAsyncCommandInfoPtr boxAsyncInfo = BoxAsyncCommandInfoPtr(new BoxAsyncCommandInfo(cmdType, boxPtr, boxInfoPtr)); + + m_vecBoxAsyncCommandList.push_back(boxAsyncInfo); + LogD("m_vecBoxAsyncCommandList added = %d ",m_vecBoxAsyncCommandList.size()); + + if (!m_boxLoadBalanceTimer) { + // start timer for clearing existing snapshot in case of only pd open + m_boxLoadBalanceTimer = ecore_timer_add(BOX_UPDATE_TIME, requestBoxLoadBalanceCallback, this); + m_updateTimeCount = BOX_UPDATE_TIME; + LogD("timer launched"); + } +} + +void BoxLoadBalancer::pushBoxAsyncCommandIntoQueue(request_box_cmd_type cmdType, IBoxPtr boxPtr, std::string& appContentInfo) +{ + BoxAsyncCommandInfoPtr boxAsyncInfo = BoxAsyncCommandInfoPtr(new BoxAsyncCommandInfo(cmdType, boxPtr, appContentInfo)); + + m_vecBoxAsyncCommandList.push_back(boxAsyncInfo); + LogD("m_vecBoxAsyncCommandList added = %d ",m_vecBoxAsyncCommandList.size()); + + if (!m_boxLoadBalanceTimer) { + // start timer for clearing existing snapshot in case of only pd open + m_boxLoadBalanceTimer = ecore_timer_add(BOX_UPDATE_TIME, requestBoxLoadBalanceCallback, this); + LogD("timer launched"); + } +} + +void BoxLoadBalancer::pushBoxAsyncCommandIntoTop(request_box_cmd_type cmdType, IBoxPtr boxPtr, BoxInfoPtr boxInfoPtr) +{ + BoxAsyncCommandInfoPtr boxAsyncInfo = BoxAsyncCommandInfoPtr(new BoxAsyncCommandInfo(cmdType, boxPtr, boxInfoPtr)); + m_vecBoxAsyncCommandList.insert(m_vecBoxAsyncCommandList.begin(), boxAsyncInfo); + LogD("m_vecBoxAsyncCommandList added = %d ",m_vecBoxAsyncCommandList.size()); + + if (!m_boxLoadBalanceTimer) { + // start timer for clearing existing snapshot in case of only pd open + m_boxLoadBalanceTimer = ecore_timer_add(BOX_UPDATE_TIME, requestBoxLoadBalanceCallback, this); + m_updateTimeCount = BOX_UPDATE_TIME; + LogD("timer launched"); + } +} + +void BoxLoadBalancer::stopLoadBalancer() +{ + if (m_boxLoadBalanceTimer) { + ecore_timer_del(m_boxLoadBalanceTimer); + m_boxLoadBalanceTimer = NULL; + } + m_vecBoxAsyncCommandList.clear(); +} diff --git a/src_wearable/Core/BoxLoadBalancer.h b/src_wearable/Core/BoxLoadBalancer.h new file mode 100755 index 0000000..3500396 --- /dev/null +++ b/src_wearable/Core/BoxLoadBalancer.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file BoxLoadBalancer.h + * @author Minhyung Ko (minhyung.ko@samsung.com) + */ +#ifndef BOX_LOAD_BALANCER_H +#define BOX_LOAD_BALANCER_H + +#include <Ecore.h> +#include <memory> +#include <string> +#include <vector> +#include "BoxData.h" +#include "IBox.h" +#include "IBoxManager.h" + +typedef enum { + BOX_AYNC_REQUEST_CMD_SHOW, + BOX_AYNC_REQUEST_CMD_RESUME, + BOX_AYNC_REQUEST_CMD_UPDATE +} request_box_cmd_type; + + +class BoxAsyncCommandInfo +{ +public: + BoxAsyncCommandInfo() {}; + BoxAsyncCommandInfo(request_box_cmd_type, IBoxPtr, BoxInfoPtr); + BoxAsyncCommandInfo(request_box_cmd_type, IBoxPtr, std::string&); + ~BoxAsyncCommandInfo() {}; + + request_box_cmd_type getType() { return m_type; } + IBoxPtr getBoxPtr() { return m_box; } + BoxInfoPtr getBoxInfoPtr() {return m_boxInfo; } + std::string getAppContentInfo() {return m_appContentInfo; } + +private: + request_box_cmd_type m_type; + IBoxPtr m_box; + BoxInfoPtr m_boxInfo; + std::string m_appContentInfo; +}; + +typedef std::shared_ptr<BoxAsyncCommandInfo> BoxAsyncCommandInfoPtr; + +class BoxLoadBalancer +{ +public: + BoxLoadBalancer(); + ~BoxLoadBalancer(); + + static Eina_Bool requestBoxLoadBalanceCallback(void* data); + + void eraseBoxAsyncCommandFromQueue(IBoxPtr boxPtr); + void pushBoxAsyncCommandIntoQueue(request_box_cmd_type type, IBoxPtr boxPtr, BoxInfoPtr boxInfoPtr); + void pushBoxAsyncCommandIntoQueue(request_box_cmd_type, IBoxPtr, std::string&); + void pushBoxAsyncCommandIntoTop(request_box_cmd_type cmdType, IBoxPtr boxPtr, BoxInfoPtr boxInfoPtr); + void stopLoadBalancer(); + +private: + // timer for load balance of boxes + Ecore_Timer* m_boxLoadBalanceTimer; + std::vector<BoxAsyncCommandInfoPtr> m_vecBoxAsyncCommandList; + float m_updateTimeCount; +}; +#endif // BOX_LOAD_BALANCER_H diff --git a/src_wearable/Core/BoxManager.cpp b/src_wearable/Core/BoxManager.cpp new file mode 100755 index 0000000..8f1bef5 --- /dev/null +++ b/src_wearable/Core/BoxManager.cpp @@ -0,0 +1,471 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file BoxManager.cpp + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#include "config.h" +#include "BoxManager.h" + +#include <string> +#include <map> +#include <ctime> +#include <EWebKit2.h> +#include <Plugin/IBoxPluginFactory.h> +#include <Plugin/box_plugin_interface.h> +#include <vconf.h> +#include "Util/Log.h" +#include "Util/Util.h" +#include "IBox.h" +#include "Box.h" +#include "BoxData.h" + +static const std::string defaultBoxType("app"); + +BoxManager::BoxManager(IBoxPluginFactoryPtr factory) + : m_boxFactory(factory) + , m_boxLoadBalancer() +{ + LogD("enter"); +} + +BoxManager::~BoxManager() +{ + LogD("enter"); +} + +bool BoxManager::doCommand(const request_cmd_type type, const BoxInfoPtr& boxInfo) +{ + bool result = false; + + switch (type) { + case REQUEST_CMD_ADD_BOX: + result = requestAddBox(boxInfo, m_defaultContext); + break; + case REQUEST_CMD_REMOVE_BOX: + if (boxInfo->instanceId.empty() && !boxInfo->boxId.empty()) { + result = requestRemoveBoxByBoxId(boxInfo); + break; + } + if (!boxInfo->instanceId.empty()) { + result = requestRemoveBoxByInstanceId(boxInfo); + break; + } + case REQUEST_CMD_RESIZE_BOX: + result = requestResizeBox(boxInfo->instanceId, boxInfo->boxWidth, boxInfo->boxHeight); + break; + case REQUEST_CMD_RESUME_BOX: + result = requestResumeBox(boxInfo->instanceId); + break; + case REQUEST_CMD_PAUSE_BOX: + result = requestPauseBox(boxInfo->instanceId); + break; + case REQUEST_CMD_RESUME_ALL: + result = requestResumeAll(); + break; + case REQUEST_CMD_PAUSE_ALL: + result = requestPauseAll(); + break; + case REQUEST_CMD_OPEN_PD: + result = requestOpenPd(boxInfo->instanceId, + boxInfo->pdWidth, boxInfo->pdHeight, + boxInfo->pdX, boxInfo->pdY); + break; + case REQUEST_CMD_CLOSE_PD: + result = requestClosePd(boxInfo->instanceId); + break; + case REQUEST_CMD_CHANGE_PERIOD: + result = requestChangePeriod(boxInfo->instanceId, boxInfo->period); + break; + case REQUEST_CMD_UPDATE_BOX: + result = requestUpdateBox(boxInfo->boxId, boxInfo->appContentInfo); + break; + case REQUEST_CMD_UPDATE_ALL: + result = requestUpdateAll(boxInfo->instanceId); + break; + case REQUEST_CMD_UPDATE_APPBOX: + result = requestUpdateAppBox(boxInfo->instanceId); + break; + default: + LogD("not available request type"); + break; + } + + return result; +} + +bool BoxManager::requestAddBox(BoxInfoPtr boxInfo, EwkContextPtr ewkContext) +{ + LogD("enter"); + IBoxPtr box; + + // create new box + try { + if (!ewkContext) { + if (!m_defaultContext) { + m_defaultContext = EwkContextPtr(ewk_context_new(), EwkContextDeleter()); + } + ewkContext = m_defaultContext; + } + + initEwkContextSetting(ewkContext); + box = Box::create(boxInfo, m_boxFactory, ewkContext); + } catch (...) { + LogD("exection occurs during adding box"); + return false; + } + + m_boxLoadBalancer.pushBoxAsyncCommandIntoTop(BOX_AYNC_REQUEST_CMD_SHOW, box, boxInfo); + + insertBoxMap(boxInfo->instanceId, box); + return true; +} + +bool BoxManager::requestRemoveBox(std::string& instanceId) +{ + LogD("enter"); + IBoxPtr box = searchBoxMap(instanceId); + if (!box) { + return false; + } + + if (!box->hide()) { + return false; + } + + m_boxMap.erase(instanceId); + return true; +} + +bool BoxManager::requestRemoveBoxByInstanceId(BoxInfoPtr boxInfo) +{ + LogD("enter"); + + IBoxPtr box = searchBoxMap(boxInfo->instanceId); + m_boxLoadBalancer.eraseBoxAsyncCommandFromQueue(box); + + if (!requestRemoveBox(boxInfo->instanceId)) { + return false; + } + eraseBoxMap(boxInfo->instanceId); + updateEwkContext(boxInfo->boxId); + return true; +} + +bool BoxManager::requestRemoveBoxByBoxId(BoxInfoPtr boxInfo) +{ + LogD("enter"); + + bool found = false; + for (auto it = m_boxMap.begin(); it != m_boxMap.end(); ) { + if (it->first.find(boxInfo->boxId) == std::string::npos) { + ++it; + continue; + } + + IBoxPtr box = searchBoxMap(boxInfo->instanceId); + m_boxLoadBalancer.eraseBoxAsyncCommandFromQueue(box); + + found = true; + it->second->hide(); + m_boxMap.erase((it++)->first); + } + + if (!found) { + return false; + } + + updateEwkContext(boxInfo->boxId); + return true; +} + +bool BoxManager::requestResizeBox(std::string& instanceId, int width, int height) +{ + LogD("enter"); + IBoxPtr box = searchBoxMap(instanceId); + if (!box) { + return false; + } + + m_boxLoadBalancer.eraseBoxAsyncCommandFromQueue(box); + return box->resize(width, height); +} + +bool BoxManager::requestResumeBox(std::string& instanceId) +{ + LogD("enter"); + IBoxPtr box = searchBoxMap(instanceId); + if (!box) { + return false; + } + BoxInfoPtr boxInfo; + box->setCurrent(); + + if (box->needToUpdate()) { + m_boxLoadBalancer.pushBoxAsyncCommandIntoQueue(BOX_AYNC_REQUEST_CMD_RESUME, box, boxInfo); + } + return true; +} + +bool BoxManager::requestPauseBox(std::string& instanceId) +{ + LogD("enter"); + IBoxPtr box = searchBoxMap(instanceId); + if (!box) { + return false; + } + m_boxLoadBalancer.eraseBoxAsyncCommandFromQueue(box); + + return box->pause(false); +} + +bool BoxManager::requestResumeAll() +{ + LogD("enter"); + m_boxLoadBalancer.stopLoadBalancer(); + + for (auto it = m_boxMap.begin(); it != m_boxMap.end(); it++) { + if (it->second->isCurrentTab()) { + std::string strBox = it->first; + requestResumeBox(strBox); + } + } + + return true; +} + +bool BoxManager::requestPauseAll() +{ + LogD("enter"); + for (auto it = m_boxMap.begin(); it != m_boxMap.end(); it++) { + if (it->second->isCurrentTab()) { + // paused by entering background + it->second->pause(true); + } + } + m_boxLoadBalancer.stopLoadBalancer(); + return true; +} + +bool BoxManager::requestOpenPd( + std::string& instanceId, + int width, int height, double x, double y) +{ + LogD("enter"); + IBoxPtr box = searchBoxMap(instanceId); + if (!box) { + return false; + } + + m_boxLoadBalancer.eraseBoxAsyncCommandFromQueue(box); + + return box->openPd(width, height, x, y); +} + +bool BoxManager::requestClosePd(std::string& instanceId) +{ + LogD("enter"); + IBoxPtr box = searchBoxMap(instanceId); + if (!box) { + return false; + } + + return box->closePd(); +} + +bool BoxManager::requestChangePeriod(std::string& instanceId, float period) +{ + LogD("enter"); + IBoxPtr box = searchBoxMap(instanceId); + if (!box) { + return false; + } + + return box->changePeriod(period); +} + +bool BoxManager::requestUpdateBox(std::string& boxId, std::string& appContentInfo) +{ + LogD("enter"); + + IBoxPtr box; + box.reset(); + + for (auto it = m_boxMap.begin(); it != m_boxMap.end(); ++it) { + if (it->first.find(boxId) == std::string::npos) { + continue; + } + box = it->second; + box->setNeedToUpdate(); + m_boxLoadBalancer.eraseBoxAsyncCommandFromQueue(box); + m_boxLoadBalancer.pushBoxAsyncCommandIntoQueue(BOX_AYNC_REQUEST_CMD_UPDATE, box, appContentInfo); + } + + return true; +} + +bool BoxManager::requestUpdateAll(std::string& instanceId) +{ + LogD("enter"); + UNUSED_PARAM(instanceId); + + IBoxPtr box; + box.reset(); + + m_boxLoadBalancer.stopLoadBalancer(); + + for (auto it = m_boxMap.begin(); it != m_boxMap.end(); ++it) { + if (it->second) { + box = it->second; + box->setNeedToUpdate(); + + if (!box->isPaused()) { + m_boxLoadBalancer.pushBoxAsyncCommandIntoQueue(BOX_AYNC_REQUEST_CMD_UPDATE, box, box->getBoxInfo()->appContentInfo); + } + // TODO: box->update(requestTime, box->getBoxInfo()->appContentInfo); + } + } + return true; +} + +bool BoxManager::requestUpdateAppBox(std::string& instanceId) +{ + LogD("enter"); + UNUSED_PARAM(instanceId); + + IBoxPtr box; + box.reset(); + + for (auto it = m_boxMap.begin(); it != m_boxMap.end(); ++it) { + if (it->second) { + box = it->second; + + if(box->getBoxInfo()->boxType.find(defaultBoxType) == std::string::npos) { + continue; + } + m_boxLoadBalancer.eraseBoxAsyncCommandFromQueue(box); + box->setNeedToUpdate(); + if (!box->isPaused()) { + m_boxLoadBalancer.pushBoxAsyncCommandIntoQueue(BOX_AYNC_REQUEST_CMD_UPDATE, box, box->getBoxInfo()->appContentInfo); + } + } + } + return true; +} + +void BoxManager::updateEwkContext(std::string& boxId) +{ + // this should be implemented by derived class + UNUSED_PARAM(boxId); +} + +int BoxManager::getBoxCount(std::string appId) +{ + int count = 0; + for (auto it = m_boxMap.begin(); it != m_boxMap.end(); it++) { + if (it->first.find(appId) == std::string::npos) { + continue; + } + count++; + } + return count; +} + +void BoxManager::insertBoxMap(std::string& instanceId, IBoxPtr box) +{ + if (!searchBoxMap(instanceId)) { + LogD("insert box to map: %s", instanceId.c_str()); + m_boxMap.insert(BoxMapPair(instanceId, box)); + } else { + LogD("this box was already inserted!"); + } +} + +void BoxManager::eraseBoxMap(std::string& instanceId) +{ + LogD("erase box to map"); + if (!searchBoxMap(instanceId)) { + LogD("not available box"); + return; + } + + m_boxMap.erase(instanceId); +} + +void BoxManager::updateBoxMap(std::string& instanceId, IBoxPtr box) +{ + if (searchBoxMap(instanceId)) { + eraseBoxMap(instanceId); + } + + insertBoxMap(instanceId, box); +} + +IBoxPtr BoxManager::searchBoxMap(std::string& instanceId) +{ + LogD("enter"); + IBoxPtr box; + box.reset(); + auto it = m_boxMap.find(instanceId); + if (it != m_boxMap.end()) { + LogD("found box: %s (%p)", it->first.c_str(), it->second.get()); + box = it->second; + } + + return box; +} + +void BoxManager::clearBoxMap() +{ + m_boxMap.clear(); +} + +void BoxManager::EwkContextDeleter::operator()(Ewk_Context* ptr) +{ + LogD("ewk context delete"); + if (ptr) { + ewk_object_unref(ptr); + } +} + +void BoxManager::initEwkContextSetting(EwkContextPtr ewkContext) +{ + LogD("enter"); + + // proxy server setting + char *proxy = vconf_get_str(VCONFKEY_NETWORK_PROXY); + std::string dummyProxy("0.0.0.0"); + if (proxy && strlen(proxy) && (dummyProxy != proxy)) { + LogD("proxy address: %s", proxy); + ewk_context_proxy_uri_set(ewkContext.get(), proxy); + } else { + LogD("proxy address is empty"); + ewk_context_proxy_uri_set(ewkContext.get(), NULL); + } + + if (proxy) { + free(proxy); + } + + Ewk_Cookie_Manager *ewkCookieManager; + ewkCookieManager = + ewk_context_cookie_manager_get(ewkContext.get()); + ewk_cookie_manager_accept_policy_set(ewkCookieManager, + EWK_COOKIE_ACCEPT_POLICY_ALWAYS); +#if !ENABLE(WEBKIT_UPVERSION) + ewk_context_tizen_extensible_api_set(ewkContext.get(), EWK_EXTENSIBLE_API_SUPPORT_MULTIMEDIA, EINA_FALSE); +#endif +} diff --git a/src_wearable/Core/BoxManager.h b/src_wearable/Core/BoxManager.h new file mode 100755 index 0000000..3617d96 --- /dev/null +++ b/src_wearable/Core/BoxManager.h @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file BoxManager.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef BOX_MANAGER_H +#define BOX_MANAGER_H + +#include <map> +#include <string> +#include <memory> +#include <Plugin/box_plugin_interface.h> +#include <Plugin/IBoxPluginFactory.h> +#include "BoxData.h" +#include "BoxLoadBalancer.h" +#include "IBox.h" +#include "IBoxManager.h" + +#define EXPORT_CLASS __attribute__ ((visibility("default"))) + +class EXPORT_CLASS BoxManager: public IBoxManager { + public: + static IBoxManagerPtr create(IBoxPluginFactoryPtr factory) + { + return IBoxManagerPtr(new BoxManager(factory)); + }; + virtual bool doCommand(const request_cmd_type type, const BoxInfoPtr& boxInfo); + virtual ~BoxManager(); + + protected: + virtual bool requestAddBox(BoxInfoPtr boxInfo, EwkContextPtr ewkContext); + virtual bool requestRemoveBox(std::string& instanceId); // deprecated + virtual bool requestRemoveBoxByInstanceId(BoxInfoPtr boxInfo); + virtual bool requestRemoveBoxByBoxId(BoxInfoPtr boxInfo); + virtual bool requestResizeBox(std::string& instanceId, int width, int height); + virtual bool requestResumeBox(std::string& instanceId); + virtual bool requestPauseBox(std::string& instanceId); + virtual bool requestResumeAll(); + virtual bool requestPauseAll(); + virtual bool requestOpenPd( + std::string& instanceId, + int width, int height, double x, double y); + virtual bool requestClosePd(std::string& instanceId); + virtual bool requestChangePeriod(std::string& instanceId, float period); + virtual bool requestUpdateBox(std::string& boxId, std::string& appContentInfo); + virtual bool requestUpdateAll(std::string& instanceId); + virtual bool requestUpdateAppBox(std::string& instanceId); + + virtual void updateEwkContext(std::string& boxId); + int getBoxCount(std::string appId); + + // ewk context deleter + struct EwkContextDeleter { + void operator()(Ewk_Context* ptr); + }; + + explicit BoxManager(IBoxPluginFactoryPtr factory); + IBoxPtr searchBoxMap(std::string& instanceId); + + private: + void initEwkContextSetting(EwkContextPtr ewkContext); + // map operations + void insertBoxMap(std::string& instanceId, IBoxPtr box); + void eraseBoxMap(std::string& instanceId); + void updateBoxMap(std::string& instanceId, IBoxPtr box); + void clearBoxMap(); + + typedef std::map<std::string, IBoxPtr> BoxMap; + typedef std::pair<std::string, IBoxPtr> BoxMapPair; + BoxMap m_boxMap; + IBoxPluginFactoryPtr m_boxFactory; + EwkContextPtr m_defaultContext; + + BoxLoadBalancer m_boxLoadBalancer; +}; + +#endif // BOX_MANAGER_H diff --git a/src_wearable/Core/BoxState.cpp b/src_wearable/Core/BoxState.cpp new file mode 100644 index 0000000..9460857 --- /dev/null +++ b/src_wearable/Core/BoxState.cpp @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file BoxState.cpp + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#include "IBoxContext.h" +#include "IBoxState.h" +#include "BoxState.h" + +// BoxState +void BoxState::switchState() +{ + // TODO this creation may be wrong.. + m_context->setState(IBoxStatePtr(this)); +} + +void BoxState::setContext(IBoxContextPtr context) +{ + m_context = context; +} + +IBoxContextPtr BoxState::getContext() +{ + return m_context; +} + +// BoxReadyState +IBoxStatePtr BoxInitState::permitShow() +{ + return IBoxStatePtr(BoxShowState::create(getContext())); +} + +// BoxShowState +IBoxStatePtr BoxShowState::permitShow() +{ + // In this case, existing state needn't to be changed + return IBoxStatePtr(this); +} + +IBoxStatePtr BoxShowState::permitHide() +{ + return IBoxStatePtr(BoxHideState::create(getContext())); +} + +IBoxStatePtr BoxShowState::permitOpenPd() +{ + return IBoxStatePtr(BoxOpenPdState::create(getContext())); +} + +IBoxStatePtr BoxShowState::permitPause() +{ + return IBoxStatePtr(BoxPauseState::create(getContext())); +} + +// BoxHideState +IBoxStatePtr BoxHideState::permitShutdown() +{ + // In this case, existing state needn't to be changed + // because there is no state to be changed from Hide State + return IBoxStatePtr(this); +} + +// BoxOpenPdState +IBoxStatePtr BoxOpenPdState::permitClosePd() +{ + return IBoxStatePtr(BoxClosePdState::create(getContext())); +} + +// BoxClosePdState +IBoxStatePtr BoxClosePdState::permitShow() +{ + return IBoxStatePtr(BoxShowState::create(getContext())); +} + +// BoxPauseState +IBoxStatePtr BoxPauseState::permitResume() +{ + return IBoxStatePtr(BoxResumeState::create(getContext())); +} + +IBoxStatePtr BoxPauseState::permitHide() +{ + return IBoxStatePtr(BoxHideState::create(getContext())); +} + +// BoxResumeState +IBoxStatePtr BoxResumeState::permitShow() +{ + return IBoxStatePtr(BoxShowState::create(getContext())); +} + +IBoxStatePtr BoxResumeState::permitHide() +{ + return IBoxStatePtr(BoxHideState::create(getContext())); +} diff --git a/src_wearable/Core/BoxState.h b/src_wearable/Core/BoxState.h new file mode 100644 index 0000000..5023386 --- /dev/null +++ b/src_wearable/Core/BoxState.h @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file BoxState.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef BOX_STATE +#define BOX_STATE + +#include "IBoxState.h" +#include "IBoxContext.h" + +/* +#define CHECK_BOX_STATE(currentState, operation) \ + IBoxStatePtr state; \ + try { \ + state = currentState->operation(); \ + } catch (...) { \ + return false; \ + } \ + +#define SWITCH_BOX_STATE() \ + state->switchState() \ +*/ + +#define CHECK_BOX_STATE(currentState, operation) +#define SWITCH_BOX_STATE() + +class BoxState: public IBoxState { + public: + virtual IBoxStatePtr permitShow() { throw this; }; + virtual IBoxStatePtr permitHide() { throw this; }; + virtual IBoxStatePtr permitResume() { throw this; }; + virtual IBoxStatePtr permitPause() { throw this; }; + virtual IBoxStatePtr permitOpenPd() { throw this; }; + virtual IBoxStatePtr permitClosePd() { throw this ; }; + virtual IBoxStatePtr permitShutdown() { throw this; }; + virtual void switchState(); + virtual ~BoxState() {}; + + protected: + explicit BoxState(IBoxContextPtr context) : m_context(context) {}; + IBoxContextPtr getContext(); + + private: + void setContext(IBoxContextPtr context); + IBoxContextPtr m_context; +}; + +class BoxInitState: public BoxState { + public: + static IBoxStatePtr create(IBoxContextPtr context) + { + return IBoxStatePtr(new BoxInitState(context)); + }; + virtual IBoxStatePtr permitShow(); + virtual ~BoxInitState() {}; + + private: + explicit BoxInitState(IBoxContextPtr context) : BoxState(context) {}; +}; + +class BoxShowState: public BoxState { + public: + static IBoxStatePtr create(IBoxContextPtr context) + { + return IBoxStatePtr(new BoxShowState(context)); + }; + virtual IBoxStatePtr permitShow(); + virtual IBoxStatePtr permitHide(); + virtual IBoxStatePtr permitOpenPd(); + virtual IBoxStatePtr permitPause(); + virtual ~BoxShowState() {}; + + private: + explicit BoxShowState(IBoxContextPtr context) : BoxState(context) {}; +}; + +class BoxHideState: public BoxState { + public: + static IBoxStatePtr create(IBoxContextPtr context) + { + return IBoxStatePtr(new BoxHideState(context)); + }; + virtual IBoxStatePtr permitShutdown(); + virtual ~BoxHideState() {}; + + private: + explicit BoxHideState(IBoxContextPtr context) : BoxState(context) {}; +}; + +class BoxOpenPdState: public BoxState { + public: + static IBoxStatePtr create(IBoxContextPtr context) + { + return IBoxStatePtr(new BoxOpenPdState(context)); + }; + virtual IBoxStatePtr permitClosePd(); + virtual ~BoxOpenPdState() {}; + + private: + explicit BoxOpenPdState(IBoxContextPtr context) : BoxState(context) {}; +}; + +class BoxClosePdState: public BoxState { + public: + static IBoxStatePtr create(IBoxContextPtr context) + { + return IBoxStatePtr(new BoxClosePdState(context)); + }; + virtual IBoxStatePtr permitShow(); + virtual ~BoxClosePdState() {}; + + private: + explicit BoxClosePdState(IBoxContextPtr context) : BoxState(context) {}; +}; + +class BoxPauseState: public BoxState { + public: + static IBoxStatePtr create(IBoxContextPtr context) + { + return IBoxStatePtr(new BoxPauseState(context)); + }; + virtual IBoxStatePtr permitResume(); + virtual IBoxStatePtr permitHide(); + virtual ~BoxPauseState() {}; + + private: + explicit BoxPauseState(IBoxContextPtr context) : BoxState(context) {}; +}; + +class BoxResumeState: public BoxState { + public: + static IBoxStatePtr create(IBoxContextPtr context) + { + return IBoxStatePtr(new BoxResumeState(context)); + }; + virtual IBoxStatePtr permitShow(); + virtual IBoxStatePtr permitHide(); + virtual ~BoxResumeState() {}; + + private: + explicit BoxResumeState(IBoxContextPtr context) : BoxState(context) {}; +}; +#endif // BOX_STATE diff --git a/src_wearable/Core/BoxUpdateTimer.cpp b/src_wearable/Core/BoxUpdateTimer.cpp new file mode 100644 index 0000000..67dcd19 --- /dev/null +++ b/src_wearable/Core/BoxUpdateTimer.cpp @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file BoxUpdateTimer.cpp + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#include <Ecore.h> +#include <Core/Util/Log.h> +#include "BoxUpdateTimer.h" + +#define UPDATE_TIME_MIN 1800.0f + +BoxUpdateTimer::BoxUpdateTimer(float period, Ecore_Task_Cb callback, void* data) + : m_period(period) + , m_callback(callback) + , m_data(data) + , m_timer() + , m_startTime() + , m_bTimerRunning(false) +{ + LogD("enter"); +} + +BoxUpdateTimer::~BoxUpdateTimer() +{ + LogD("enter"); +} + +void BoxUpdateTimer::start() +{ + if (m_period <= 0.0f ) { + return; + } + + if (m_period < UPDATE_TIME_MIN) { + LogD("reset to minimum period(%f)", UPDATE_TIME_MIN); + m_period = UPDATE_TIME_MIN; + } + + if (m_timer) { + stop(); + } + + m_timer = ecore_timer_add(m_period, m_callback, m_data); + m_startTime = time(NULL); + m_bTimerRunning = true; +} + +void BoxUpdateTimer::continueTimer(float period) +{ + if (period <= 0.0f ) { + return; + } + + if (m_timer) { + stop(); + } + + m_timer = ecore_timer_add(period, m_callback, m_data); + // this function does not need m_startTime beacuse this is concept for continue not really start + // box.h update algorithm used boxupdatetimer + m_bTimerRunning = true; +} + +void BoxUpdateTimer::stop() +{ + if (m_timer) { + ecore_timer_del(m_timer); + m_timer = NULL; + } + m_bTimerRunning = false; +} + +void BoxUpdateTimer::resume() +{ + LogD("enter"); + ecore_timer_thaw(m_timer); +} + +void BoxUpdateTimer::pause() +{ + LogD("enter"); + ecore_timer_freeze(m_timer); +} + +void BoxUpdateTimer::restart() +{ + if (m_timer) { + ecore_timer_reset(m_timer); + } else { + start(); + } +} + +void BoxUpdateTimer::setPeriod(float period) +{ + m_period = period; + restart(); +} diff --git a/src_wearable/Core/BoxUpdateTimer.h b/src_wearable/Core/BoxUpdateTimer.h new file mode 100644 index 0000000..1238cc0 --- /dev/null +++ b/src_wearable/Core/BoxUpdateTimer.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file BoxUpdateTimer.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef BOX_UPDATE_TIMER_H +#define BOX_UPDATE_TIMER_H + +#include <ctime> +#include <Ecore.h> +#include "Util/ITimer.h" + +class BoxUpdateTimer: public ITimer { + public: + static ITimerPtr create(float period, Ecore_Task_Cb callback, void* data) + { + return ITimerPtr(new BoxUpdateTimer(period, callback, data)); + }; + void start(); + // instant timer for web-provider box contorl system + void continueTimer(float period); + void stop(); + void resume(); + void pause(); + void restart(); + void setPeriod(float period); + float getPeriod() { return m_period; } + time_t getStartTime() { return m_startTime; } + bool isRunning() { return m_bTimerRunning; } + ~BoxUpdateTimer(); + + private: + explicit BoxUpdateTimer(float period, Ecore_Task_Cb callback, void* data); + float m_period; + Ecore_Task_Cb m_callback; + void* m_data; + Ecore_Timer* m_timer; + time_t m_startTime; + bool m_bTimerRunning; +}; + +#endif // BOX_UPDATE_TIMER_H diff --git a/src_wearable/Core/Buffer/BoxRenderBuffer.cpp b/src_wearable/Core/Buffer/BoxRenderBuffer.cpp new file mode 100755 index 0000000..8a5874b --- /dev/null +++ b/src_wearable/Core/Buffer/BoxRenderBuffer.cpp @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file BoxRenderBuffer.cpp + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#include <string> +#include <Ecore.h> +#include <Evas.h> +#include <provider.h> +#include <provider_buffer.h> +#include <Core/Util/Log.h> +#include <Core/Util/Util.h> +#include <API/web_provider_livebox_info.h> +#include "RenderBuffer.h" +#include "BoxRenderBuffer.h" + +BoxRenderBuffer::BoxRenderBuffer(BoxInfoPtr boxInfo, TouchViewCallback touchCallback) + : m_boxId(boxInfo->boxId) + , m_instanceId(boxInfo->instanceId) + , m_width(boxInfo->boxWidth) + , m_height(boxInfo->boxHeight) + , m_contentInfo(boxInfo->contentInfo) + , m_touchCallback(touchCallback) +{ +} + +BoxRenderBuffer::~BoxRenderBuffer() +{ +} + +BufferInfoPtr BoxRenderBuffer::acquireBuffer() +{ + LogD("enter"); + + bool touchable = true; + const char* type = web_provider_livebox_get_box_type(m_boxId.c_str()); + + if (type) { + touchable = web_provider_livebox_get_mouse_event(m_boxId.c_str()) || + strncmp(type, "app", 3); + } + + BufferInfoPtr bufferInfo = + provider_buffer_acquire( + TYPE_LB, + m_boxId.c_str(), + m_instanceId.c_str(), + m_width, + m_height, + sizeof(int), + touchable ? handleTouchEventCallback : NULL, + this); + return bufferInfo; +} + +void BoxRenderBuffer::updateBuffer() +{ + provider_send_updated( + m_boxId.c_str(), + m_instanceId.c_str(), + m_width, m_height, + 0, m_contentInfo.c_str(), NULL); +} + +int BoxRenderBuffer::handleTouchEventCallback( + BufferInfoPtr bufferInfo, + buffer_event event, + double timestamp, + double x, + double y, + void* data) +{ + LogD("enter"); + UNUSED_PARAM(bufferInfo); + + BoxRenderBuffer* This = static_cast<BoxRenderBuffer*>(data); + TouchType type; + switch (event) { + case BUFFER_EVENT_MOVE: + type = TOUCH_EVENT_MOVE; + break; + case BUFFER_EVENT_DOWN: + type = TOUCH_EVENT_DOWN; + break; + case BUFFER_EVENT_UP: + type = TOUCH_EVENT_UP; + break; + default: + type = TOUCH_EVENT_UNRECOGNIZED; + break; + } + + if (type == TOUCH_EVENT_UNRECOGNIZED) { + return -1; + } + + This->didHandleTouchEvent(type, timestamp, x, y); + + // call touch callback of renderView + This->m_touchCallback((int)(x * This->m_width), (int)(y * This->m_height)); + + return 0; +} + +void BoxRenderBuffer::didHandleTouchEvent( + TouchType type, double timestamp, double x, double y) +{ + UNUSED_PARAM(timestamp); + + // timestamp format sent by viewer is not same to the timestamp format used by webkit-efl + // so web-provider should get timestamp using ecore_time_get() + // and then feed event with the timestamp to webkit + + LogD("enter"); + switch (type) { + case TOUCH_EVENT_MOVE: + LogD("move event"); + evas_event_feed_mouse_move( + getCanvas(), x * m_width, y * m_height, ecore_time_get() * 1000, NULL); + break; + case TOUCH_EVENT_DOWN: + LogD("down event"); + evas_event_feed_mouse_move( + getCanvas(), x * m_width, y * m_height, ecore_time_get() * 1000, NULL); + evas_event_feed_mouse_down( + getCanvas(), 1, EVAS_BUTTON_NONE, 0, NULL); + break; + case TOUCH_EVENT_UP: + LogD("up event"); + evas_event_feed_mouse_up( + getCanvas(), 1, EVAS_BUTTON_NONE, 0, NULL); + break; + default: + LogD("wrong event"); + break; + } +} diff --git a/src_wearable/Core/Buffer/BoxRenderBuffer.h b/src_wearable/Core/Buffer/BoxRenderBuffer.h new file mode 100644 index 0000000..3b0b896 --- /dev/null +++ b/src_wearable/Core/Buffer/BoxRenderBuffer.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file BoxRenderBuffer.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef BOX_RENDER_BUFFER_H +#define BOX_RENDER_BUFFER_H + +#include <string> +#include <provider_buffer.h> +#include <Core/BoxData.h> +#include <Core/View/RenderView.h> +#include "IRenderBuffer.h" +#include "RenderBuffer.h" + +#define EXPORT_CLASS __attribute__ ((visibility("default"))) + +class EXPORT_CLASS BoxRenderBuffer: public RenderBuffer { + public: + enum TouchType { + TOUCH_EVENT_UNRECOGNIZED = -1, + TOUCH_EVENT_MOVE = 0, + TOUCH_EVENT_DOWN, + TOUCH_EVENT_UP + }; + + static IRenderBufferPtr create(BoxInfoPtr boxInfo, TouchViewCallback touchCallback) + { + return IRenderBufferPtr(new BoxRenderBuffer(boxInfo, touchCallback)); + }; + virtual ~BoxRenderBuffer(); + + protected: + // this function may be overriden by derived class + virtual void didHandleTouchEvent( + TouchType type, double timestamp, double x, double y); + explicit BoxRenderBuffer(BoxInfoPtr boxInfo, TouchViewCallback touchCallback); + + private: + // RenderBuffer Implementation + int getWidth() { return m_width; }; + int getHeight() { return m_height; }; + void setWidth(int width) { m_width = width; }; + void setHeight(int height) { m_height = height; }; + BufferInfoPtr acquireBuffer(); + void updateBuffer(); + + // touch callback from master provider + static int handleTouchEventCallback( + BufferInfoPtr bufferInfo, + buffer_event event, + double timestamp, + double x, + double y, + void* data); + + // members + std::string m_boxId; + std::string m_instanceId; + std::string m_contentInfo; + int m_width; + int m_height; + TouchViewCallback m_touchCallback; +}; + +#endif // BOX_RENDER_BUFFER_H diff --git a/src_wearable/Core/Buffer/CMakeLists.txt b/src_wearable/Core/Buffer/CMakeLists.txt new file mode 100644 index 0000000..06396ec --- /dev/null +++ b/src_wearable/Core/Buffer/CMakeLists.txt @@ -0,0 +1,65 @@ +# Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved +# +# Licensed under the Flora License, Version 1.1 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://floralicense.org/license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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) + +SET(TARGET_NAME ${TARGET_CORE_BUFFER}) +SET(DEPS ${TARGET_NAME}_DEPS) + +PKG_CHECK_MODULES(${DEPS} + ecore + ecore-evas + evas + provider + livebox-service + elementary + dlog + REQUIRED +) +ADD_DEFINITIONS(${${DEPS}_CFLAGS}) + +SET(SRCS + ${CMAKE_CURRENT_SOURCE_DIR}/RenderBuffer.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/BoxRenderBuffer.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/PdRenderBuffer.cpp +) + +SET(HEADERS + ${${DEPS}_INCLUDE_DIRS} + ${CMAKE_CURRENT_SOURCE_DIR} +) +INCLUDE_DIRECTORIES(${HEADERS}) + +ADD_LIBRARY(${TARGET_NAME} STATIC ${SRCS}) + +SET_TARGET_PROPERTIES(${TARGET_NAME} PROPERTIES + COMPILE_FLAGS -fPIC + LINK_FLAGS "-Wl,--as-needed -Wl,--hash-style=both" +) + +SET_TARGET_PROPERTIES(${TARGET_NAME} + PROPERTIES + SOVERSION ${CMAKE_PROJECT_API_VERSION} + VERSION ${CMAKE_PROJECT_VERSION} +) + +TARGET_LINK_LIBRARIES(${TARGET_NAME} + ${${DEPS}_LIBRARIES} +) + +GET_FILENAME_COMPONENT(CURRENT_DIR_NAME ${CMAKE_CURRENT_SOURCE_DIR} NAME) +GET_FILENAME_COMPONENT(PARENT_DIR_ABSOLUTE_PATH ${CMAKE_CURRENT_SOURCE_DIR} PATH) +GET_FILENAME_COMPONENT(PARENT_DIR_NAME ${PARENT_DIR_ABSOLUTE_PATH} NAME) + +INSTALL_FILE(IRenderBuffer.h include/${PROJECT_NAME}/${PARENT_DIR_NAME}/${CURRENT_DIR_NAME}) diff --git a/src_wearable/Core/Buffer/IRenderBuffer.h b/src_wearable/Core/Buffer/IRenderBuffer.h new file mode 100644 index 0000000..ac28817 --- /dev/null +++ b/src_wearable/Core/Buffer/IRenderBuffer.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file IRenderBuffer.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef I_RENDER_BUFFER_H +#define I_RENDER_BUFFER_H + +#include <memory> +#include <Evas.h> +#include <Util/Noncopyable.h> + +class IRenderBuffer: Noncopyable { + public: + virtual bool allocate(bool hwEnable = false) = 0; + virtual bool reallocate(int width, int height) = 0; + virtual bool free() = 0; + virtual void startCanvasUpdate() = 0; + virtual void stopCanvasUpdate() = 0; + virtual Evas_Object* getWindow() = 0; + virtual Evas_Object* getSnapshot() = 0; + virtual void* getBufferAddr() = 0; + virtual ~IRenderBuffer() {}; + virtual void setWebView(Evas_Object* webview) = 0; + virtual Evas_Object* getWebView() = 0; + virtual Evas* getCanvas() = 0; +}; + +typedef std::shared_ptr<IRenderBuffer> IRenderBufferPtr; + +#endif diff --git a/src_wearable/Core/Buffer/PdRenderBuffer.cpp b/src_wearable/Core/Buffer/PdRenderBuffer.cpp new file mode 100644 index 0000000..48bf22b --- /dev/null +++ b/src_wearable/Core/Buffer/PdRenderBuffer.cpp @@ -0,0 +1,247 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file PdRenderBuffer.cpp + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ + +#include "PdRenderBuffer.h" + +#include "config.h" + +#include <string> +#include <Ecore.h> +#include <Evas.h> +#include <ewk_view.h> +#include <provider.h> +#include <Elementary.h> +#include <livebox-service.h> +#include <provider_buffer.h> +#include <Core/Util/Log.h> +#include <Core/Util/Util.h> +#include "RenderBuffer.h" + +PdRenderBuffer::PdRenderBuffer(BoxInfoPtr boxInfo, TouchViewCallback touchCallback) + : m_boxId(boxInfo->boxId) + , m_instanceId(boxInfo->instanceId) + , m_width(boxInfo->pdWidth) + , m_height(boxInfo->pdHeight) + , m_touchCallback(touchCallback) +{ +} + +PdRenderBuffer::~PdRenderBuffer() +{ +} + +BufferInfoPtr PdRenderBuffer::acquireBuffer() +{ + BufferInfoPtr bufferInfo = + provider_buffer_acquire( + TYPE_PD, + m_boxId.c_str(), + m_instanceId.c_str(), + m_width, + m_height, + sizeof(int), + handleTouchEventCallback, + this); + + m_accessibiilty = false; + return bufferInfo; +} + +void PdRenderBuffer::updateBuffer() +{ + LogD("enter"); + provider_send_desc_updated( + m_boxId.c_str(), + m_instanceId.c_str(), + NULL); +} + +int PdRenderBuffer::handleTouchEventCallback( + BufferInfoPtr bufferInfo, + buffer_event event, + double timestamp, + double x, + double y, + void* data) +{ + LogD("enter"); + UNUSED_PARAM(bufferInfo); + + PdRenderBuffer* This = static_cast<PdRenderBuffer*>(data); + TouchType type; + Elm_Access_Action_Info ActionInfo; + +#if !ENABLE(WEBKIT_UPVERSION) + switch (event) { + case BUFFER_EVENT_HIGHLIGHT: + case BUFFER_EVENT_HIGHLIGHT_NEXT: + case BUFFER_EVENT_HIGHLIGHT_PREV: + case BUFFER_EVENT_ACTIVATE: + case BUFFER_EVENT_ACTION_UP: + case BUFFER_EVENT_ACTION_DOWN: + case BUFFER_EVENT_SCROLL_UP: + case BUFFER_EVENT_SCROLL_MOVE: + case BUFFER_EVENT_SCROLL_DOWN: + case BUFFER_EVENT_UNHIGHLIGHT: + { + LogD("handleTouchEventCallback event %d x,y %f,%f", event, x,y); + int action_type = event; + ActionInfo.highlight_cycle = EINA_FALSE; + + if (!This->getWebView()) + return 0; + + Ewk_View_Smart_Data* pSmartData = (Ewk_View_Smart_Data*) evas_object_smart_data_get(This->getWebView()); + + switch (event) { + case BUFFER_EVENT_HIGHLIGHT: + { + ActionInfo.action_type = ELM_ACCESS_ACTION_HIGHLIGHT; + ActionInfo.action_by = ELM_ACCESS_ACTION_HIGHLIGHT; + if (pSmartData->api->screen_reader_action_execute(pSmartData, &ActionInfo)) { + provider_send_access_status(This->m_boxId.c_str(), This->m_instanceId.c_str(), LB_ACCESS_STATUS_DONE); + } else { + provider_send_access_status(This->m_boxId.c_str(), This->m_instanceId.c_str(), LB_ACCESS_STATUS_DONE); + } + ActionInfo.action_type = ELM_ACCESS_ACTION_READ; + break; + } + case BUFFER_EVENT_HIGHLIGHT_NEXT: + if (!This->m_accessibiilty) { + ActionInfo.action_by = ELM_ACCESS_ACTION_HIGHLIGHT; + ActionInfo.action_type = ELM_ACCESS_ACTION_HIGHLIGHT; + if (pSmartData->api->screen_reader_action_execute(pSmartData, &ActionInfo)) { + provider_send_access_status(This->m_boxId.c_str(), This->m_instanceId.c_str(), LB_ACCESS_STATUS_DONE); + } else { + provider_send_access_status(This->m_boxId.c_str(), This->m_instanceId.c_str(), LB_ACCESS_STATUS_DONE); + } + ActionInfo.action_type = ELM_ACCESS_ACTION_HIGHLIGHT_NEXT; + This->m_accessibiilty = true; + } else { + ActionInfo.action_type = ELM_ACCESS_ACTION_HIGHLIGHT_NEXT; + } + break; + case BUFFER_EVENT_HIGHLIGHT_PREV: + if (!This->m_accessibiilty) { + ActionInfo.action_by = ELM_ACCESS_ACTION_HIGHLIGHT; + ActionInfo.action_type = ELM_ACCESS_ACTION_HIGHLIGHT; + if (pSmartData->api->screen_reader_action_execute(pSmartData, &ActionInfo)) { + provider_send_access_status(This->m_boxId.c_str(), This->m_instanceId.c_str(), LB_ACCESS_STATUS_DONE); + } else { + provider_send_access_status(This->m_boxId.c_str(), This->m_instanceId.c_str(), LB_ACCESS_STATUS_DONE); + } + ActionInfo.action_type = ELM_ACCESS_ACTION_HIGHLIGHT_PREV; + This->m_accessibiilty = true; + } else { + ActionInfo.action_type = ELM_ACCESS_ACTION_HIGHLIGHT_PREV; + } + break; + case BUFFER_EVENT_ACTIVATE: + ActionInfo.action_type = ELM_ACCESS_ACTION_ACTIVATE; + break; + case BUFFER_EVENT_UNHIGHLIGHT: + ActionInfo.action_type = ELM_ACCESS_ACTION_UNHIGHLIGHT; + break; + case BUFFER_EVENT_ACTION_UP: + case BUFFER_EVENT_ACTION_DOWN: + case BUFFER_EVENT_SCROLL_UP: + case BUFFER_EVENT_SCROLL_MOVE: + case BUFFER_EVENT_SCROLL_DOWN: + default: + break; + } + int xWebview,yWebview,w,h; + evas_object_geometry_get(This->getWebView(), &xWebview, &yWebview, &w, &h); + + ActionInfo.x = xWebview + static_cast<int>(w*x); + ActionInfo.y = yWebview + static_cast<int>(h*y); + + if (pSmartData->api->screen_reader_action_execute(pSmartData, &ActionInfo)) { + provider_send_access_status(This->m_boxId.c_str(), This->m_instanceId.c_str(), LB_ACCESS_STATUS_DONE); + } else { + provider_send_access_status(This->m_boxId.c_str(), This->m_instanceId.c_str(), LB_ACCESS_STATUS_LAST); + This->m_accessibiilty = false; + } + } + return 0; + default: + break; + } +#endif // WEBKIT_UPVERSION + + switch (event) { + case BUFFER_EVENT_MOVE: + type = TOUCH_EVENT_MOVE; + break; + case BUFFER_EVENT_DOWN: + type = TOUCH_EVENT_DOWN; + break; + case BUFFER_EVENT_UP: + type = TOUCH_EVENT_UP; + break; + default: + type = TOUCH_EVENT_UNRECOGNIZED; + break; + } + + if (type == TOUCH_EVENT_UNRECOGNIZED) { + return -1; + } + + This->didHandleTouchEvent(type, timestamp, x, y); + + // call touch callback of renderView + This->m_touchCallback((int)(x * This->m_width), (int)(y * This->m_height)); + + return 0; +} + +void PdRenderBuffer::didHandleTouchEvent( + TouchType type, double timestamp, double x, double y) +{ + UNUSED_PARAM(timestamp); + + // timestamp format sent by viewer is not same to the timestamp format used by webkit-efl + // so web-provider should get timestamp using ecore_time_get() + // and then feed event with the timestamp to webkit + + switch (type) { + case TOUCH_EVENT_MOVE: + LogD("move event"); + evas_event_feed_mouse_move( + getCanvas(), x * m_width, y * m_height, ecore_time_get() * 1000, NULL); + break; + case TOUCH_EVENT_DOWN: + LogD("down event"); + evas_event_feed_mouse_move( + getCanvas(), x * m_width, y * m_height, ecore_time_get() * 1000, NULL); + evas_event_feed_mouse_down( + getCanvas(), 1, EVAS_BUTTON_NONE, 0, NULL); + break; + case TOUCH_EVENT_UP: + LogD("up event"); + evas_event_feed_mouse_up( + getCanvas(), 1, EVAS_BUTTON_NONE, 0, NULL); + break; + default: + LogD("wrong event"); + break; + } +} diff --git a/src_wearable/Core/Buffer/PdRenderBuffer.h b/src_wearable/Core/Buffer/PdRenderBuffer.h new file mode 100644 index 0000000..ecf69fd --- /dev/null +++ b/src_wearable/Core/Buffer/PdRenderBuffer.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file PdRenderBuffer.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef PD_RENDER_BUFFER_H +#define PD_RENDER_BUFFER_H + +#include <string> +#include <provider_buffer.h> +#include <Core/BoxData.h> +#include <Core/View/RenderView.h> +#include "IRenderBuffer.h" +#include "RenderBuffer.h" + +#define EXPORT_CLASS __attribute__ ((visibility("default"))) + +class EXPORT_CLASS PdRenderBuffer: public RenderBuffer { + public: + enum TouchType { + TOUCH_EVENT_UNRECOGNIZED = -1, + TOUCH_EVENT_MOVE = 0, + TOUCH_EVENT_DOWN, + TOUCH_EVENT_UP + }; + + static IRenderBufferPtr create(BoxInfoPtr boxInfo, TouchViewCallback touchCallback) + { + return IRenderBufferPtr(new PdRenderBuffer(boxInfo, touchCallback)); + }; + ~PdRenderBuffer(); + + protected: + // this function may be overriden by derived class + virtual void didHandleTouchEvent( + TouchType type, double timestamp, double x, double y); + explicit PdRenderBuffer(BoxInfoPtr boxInfo, TouchViewCallback touchCallback); + + private: + // RenderBuffer Implementation + int getWidth() { return m_width; }; + int getHeight() { return m_height; }; + void setWidth(int width) { m_width = width; }; + void setHeight(int height) { m_height = height; }; + BufferInfoPtr acquireBuffer(); + void updateBuffer(); + + // touch callback + static int handleTouchEventCallback( + BufferInfoPtr bufferInfo, + buffer_event event, + double timestamp, + double x, + double y, + void* data); + + // members + std::string m_boxId; + std::string m_instanceId; + int m_width; + int m_height; + TouchViewCallback m_touchCallback; + bool m_accessibiilty; +}; + +#endif // PD_RENDER_BUFFER_H diff --git a/src_wearable/Core/Buffer/RenderBuffer.cpp b/src_wearable/Core/Buffer/RenderBuffer.cpp new file mode 100755 index 0000000..432f847 --- /dev/null +++ b/src_wearable/Core/Buffer/RenderBuffer.cpp @@ -0,0 +1,428 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file RenderBuffer.cpp + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#include <string> +#include <Evas.h> +#include <Ecore.h> +#include <Ecore_Evas.h> +#include <provider.h> +#include <provider_buffer.h> +#include <Core/Util/Log.h> +#include <Core/Util/Util.h> +#include "IRenderBuffer.h" +#include "RenderBuffer.h" + +const char * ecoreevasdataforrenderbuffer = "ecoreevasrenderbufferforwebprovider"; + +RenderBuffer::RenderBuffer() + : m_bufferAddr(NULL) + , m_bufferInfo(NULL) + , m_hwEnable(false) + , m_webview(NULL) +{ + LogD("enter"); +} + +RenderBuffer::~RenderBuffer() +{ + LogD("enter"); +} + +bool RenderBuffer::allocate(bool hwEnable) +{ + bool ret; + + LogD("enter"); + + m_hwEnable = hwEnable; + + if (m_bufferAddr) { + free(); + m_bufferAddr = NULL; + } + + if (hwEnable) { + ret = bufferAllocationForGLRendering(); + } else + ret = bufferAllocationForSWRendering(); + + startCanvasUpdate(); + return true; +} + +bool RenderBuffer::reallocate(int width, int height) +{ + LogD("enter"); + stopCanvasUpdate(); + + // TODO This function should be implemented due to box resize operation + setWidth(width); + setHeight(height); + + Ecore_Evas* ee = ecore_evas_ecore_evas_get(m_canvas); + // resize function will invoke the freeCallback and allocateCallback again. (internally) + ecore_evas_resize(ee, getWidth(), getHeight()); + evas_object_resize(m_win, getWidth(), getHeight()); + + if (m_hwEnable) + { + bufferReAllocation(width, height); + } + + startCanvasUpdate(); + return true; +} + +bool RenderBuffer::free() +{ + if (!m_canvas) { + return false; + } + + stopCanvasUpdate(); + ecore_evas_free(ecore_evas_ecore_evas_get(m_canvas)); + m_canvas = NULL; + m_win = NULL; + + return true; +} + +void RenderBuffer::startCanvasUpdate() +{ + LogD("enter"); + evas_event_callback_del( + m_canvas, + EVAS_CALLBACK_RENDER_PRE, + preRenderCallback); + + evas_event_callback_del( + m_canvas, + EVAS_CALLBACK_RENDER_POST, + postRenderCallback); + + evas_event_callback_add( + m_canvas, + EVAS_CALLBACK_RENDER_PRE, + preRenderCallback, this); + + evas_event_callback_add( + m_canvas, + EVAS_CALLBACK_RENDER_POST, + postRenderCallback, this); + +} + +void RenderBuffer::stopCanvasUpdate() +{ + LogD("enter"); + evas_event_callback_del( + m_canvas, + EVAS_CALLBACK_RENDER_PRE, + preRenderCallback); + + evas_event_callback_del( + m_canvas, + EVAS_CALLBACK_RENDER_POST, + postRenderCallback); +} + +Evas_Object* RenderBuffer::getWindow() +{ + return m_win; +} + +void RenderBuffer::preRenderCallback(void* data, Evas* canvas, void *eventInfo) +{ + UNUSED_PARAM(eventInfo); + + RenderBuffer *buffer = static_cast<RenderBuffer*>(data); + + if ((buffer->m_hwEnable == true)) { + return; + } + + provider_buffer_pre_render(buffer->m_bufferInfo); + evas_damage_rectangle_add(canvas, 0, 0, buffer->getWidth(), buffer->getHeight()); +} + +void RenderBuffer::postRenderCallback(void* data, Evas* canvas, void* eventInfo) +{ + UNUSED_PARAM(canvas); + UNUSED_PARAM(eventInfo); + + RenderBuffer* buffer = static_cast<RenderBuffer*>(data); + + if (buffer->m_hwEnable == true) { + buffer->updateBuffer(); + } else { + evas_data_argb_unpremul(static_cast<unsigned int*>(buffer->m_bufferAddr), buffer->getWidth() * buffer->getHeight()); +#ifdef RENDER_BUFFER_VERIFY_SHOT + { + FILE *fp; + static int idx = 0; + char filename[256]; + snprintf(filename, sizeof(filename) - 1, "/tmp/render%d-%dx%d.raw", idx++, buffer->getWidth(), buffer->getHeight()); + fp = fopen(filename, "w+"); + if (fp) { + LogD("RenderShot: %s(%d)\n", filename, buffer->getWidth() * buffer->getHeight() * sizeof(int)); + fwrite(buffer->m_bufferAddr, buffer->getWidth() * buffer->getHeight() * sizeof(int), 1, fp); + fclose(fp); + } else { + LogD("Failed to open a file: %s", filename); + } + } +#endif + LogD("/tmp/render-%dx%d.raw", buffer->getWidth(), buffer->getHeight()); + + if (!provider_buffer_pixmap_is_support_hw(buffer->m_bufferInfo)) { + provider_buffer_sync(buffer->m_bufferInfo); + buffer->updateBuffer(); + } else { + provider_buffer_post_render(buffer->m_bufferInfo); + buffer->updateBuffer(); + } + } +} + +void RenderBuffer::paintColor(unsigned int color) +{ + LogD("enter"); + + if (!provider_buffer_pixmap_is_support_hw(m_bufferInfo)) { + memset(m_bufferAddr, color, getWidth() * getHeight() * 4); + provider_buffer_sync(m_bufferInfo); + updateBuffer(); + } else { + preRenderCallback(this, m_canvas, NULL); + memset(m_bufferAddr, color, getWidth() * getHeight() * 4); + postRenderCallback(this, m_canvas, NULL); + } +} + +Evas* RenderBuffer::getCanvas() +{ + return m_canvas; +} + +void* RenderBuffer::allocateCallback(void* data, int size) +{ + LogD("enter"); + UNUSED_PARAM(size); + + RenderBuffer* buffer = static_cast<RenderBuffer*>(data); + + if (buffer->m_bufferInfo) { + freeCallback(data, NULL); + } + + buffer->m_bufferInfo = buffer->acquireBuffer(); + if (!buffer->m_bufferInfo) { + return NULL; + } + + // set buffer address + if (!provider_buffer_pixmap_is_support_hw(buffer->m_bufferInfo)) { + LogD("s/w evas backend"); + buffer->m_bufferAddr = provider_buffer_ref(buffer->m_bufferInfo); + } else { + LogD("h/w evas backend"); + int ret = provider_buffer_pixmap_create_hw(buffer->m_bufferInfo); + if (ret < 0) { + LogD("can't create hw pixmap"); + } + buffer->m_bufferAddr = provider_buffer_pixmap_hw_addr(buffer->m_bufferInfo); + } + + LogD("success to allocate buffer"); + return buffer->m_bufferAddr; +} + +void RenderBuffer::freeCallback(void* data, void *pix) +{ + LogD("enter"); + UNUSED_PARAM(pix); + + RenderBuffer* buffer = static_cast<RenderBuffer*>(data); + + // destroy buffer + if (!provider_buffer_pixmap_is_support_hw(buffer->m_bufferInfo)) { + provider_buffer_unref(buffer->m_bufferAddr); + } else { + provider_buffer_pixmap_destroy_hw(buffer->m_bufferInfo); + } + + provider_buffer_release(buffer->m_bufferInfo); + + buffer->m_bufferInfo = NULL; + buffer->m_bufferAddr = NULL; + + LogD("success to free buffer"); + return; +} + +Evas_Object *RenderBuffer::getSnapshot(void) +{ + LogD("enter"); + Evas_Object *snapshot; + void *tmpBuffer; + + snapshot = evas_object_image_add(m_canvas); + if (!snapshot) + return NULL; + evas_object_image_data_set(snapshot, NULL); + evas_object_image_colorspace_set(snapshot, EVAS_COLORSPACE_ARGB8888); + evas_object_image_alpha_set(snapshot, EINA_TRUE); + evas_object_image_size_set(snapshot, getWidth(), getHeight()); + + tmpBuffer = malloc(getWidth() * getHeight() * sizeof(int)); + if (tmpBuffer) { + memcpy(tmpBuffer, m_bufferAddr, getWidth() * getHeight() * sizeof(int)); + evas_data_argb_premul( + static_cast<unsigned int*>(tmpBuffer), + getWidth() * getHeight()); + evas_object_image_data_set(snapshot, tmpBuffer); + } else { + LogD("Failed to allocate heap"); + } + + evas_object_image_data_update_add(snapshot, 0, 0, getWidth(), getHeight()); + evas_object_image_fill_set(snapshot, 0, 0, getWidth(), getHeight()); + evas_object_resize(snapshot, getWidth(), getHeight()); + + return snapshot; +} + +bool RenderBuffer::bufferAllocationForGLRendering() +{ + Ecore_Evas* ee = NULL; + + ee = ecore_evas_gl_x11_new(NULL, 0, 0, 0, getWidth(), getHeight()); + + LogD("Using %s engine!", ecore_evas_engine_name_get(ee)); + + if (!ee) { + LogD("invalid ecore evas object"); + return false; + } + + m_bufferInfo = acquireBuffer(); + if (!m_bufferInfo) { + return NULL; + } + + if (!provider_buffer_pixmap_is_support_hw(m_bufferInfo)) { + LogD("s/w evas backend"); + m_bufferAddr = provider_buffer_ref(m_bufferInfo); + } else { + LogD("h/w evas backend"); + int ret = provider_buffer_pixmap_create_hw(m_bufferInfo); + if (ret < 0) { + LogD("can't create hw pixmap"); + } + + m_bufferAddr = (void *)provider_buffer_pixmap_id(m_bufferInfo); + LogD("evas ecore provider_buffer_pixmap_id m_bufferAddr %lu", (unsigned long)m_bufferAddr); + } + + ecore_evas_activate(ee); + + Evas* e = ecore_evas_get(ee); + evas_image_cache_flush(e); + Evas_Object *eo = evas_object_rectangle_add(e); + evas_object_size_hint_weight_set(eo, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_color_set(eo, 0, 0, 0, 1); + evas_object_resize(eo, getWidth(), getHeight()); + + m_canvas = e; + m_win = eo; + + return true; +} + +bool RenderBuffer::bufferAllocationForSWRendering() +{ + Ecore_Evas* ee = NULL; + + ee = ecore_evas_buffer_allocfunc_new( + getWidth(), getHeight(), + allocateCallback, freeCallback, + this); + + LogD("Using %s engine!", ecore_evas_engine_name_get(ee)); + + if (!ee) { + LogD("invalid ecore evas object"); + return false; + } + + // alpha_set function access the canvas buffer directly, + // without pre/post render callback. + provider_buffer_pre_render(m_bufferInfo); + ecore_evas_alpha_set(ee, EINA_TRUE); + provider_buffer_post_render(m_bufferInfo); + ecore_evas_manual_render_set(ee, EINA_FALSE); + + // resize function will invoke the freeCallback and allocateCallback again. (internally) + ecore_evas_resize(ee, getWidth(), getHeight()); + ecore_evas_show(ee); + + + ecore_evas_activate(ee); + + Evas* e = ecore_evas_get(ee); + evas_image_cache_flush(e); + Evas_Object *eo = evas_object_rectangle_add(e); + evas_object_size_hint_weight_set(eo, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_color_set(eo, 0, 0, 0, 1); + evas_object_resize(eo, getWidth(), getHeight()); + + m_canvas = e; + m_win = eo; + + return true; +} + +void RenderBuffer::bufferReAllocation(int width, int height) +{ + LogD("enter"); + UNUSED_PARAM(width); + UNUSED_PARAM(height); + + provider_buffer_release(m_bufferInfo); + + m_bufferInfo = acquireBuffer(); + if (!m_bufferInfo) { + return; + } + + // set buffer address + if (!provider_buffer_pixmap_is_support_hw(m_bufferInfo)) { + LogD("s/w evas backend"); + m_bufferAddr = provider_buffer_ref(m_bufferInfo); + } else { + LogD("h/w evas backend"); + int ret = provider_buffer_pixmap_create_hw(m_bufferInfo); + if (ret < 0) { + LogD("can't create hw pixmap"); + } + m_bufferAddr = (void *)provider_buffer_pixmap_id(m_bufferInfo); + LogD("evas ecore provider_buffer_pixmap_id m_bufferAddr %lu", (unsigned long)m_bufferAddr); + } +} + diff --git a/src_wearable/Core/Buffer/RenderBuffer.h b/src_wearable/Core/Buffer/RenderBuffer.h new file mode 100644 index 0000000..64f9a91 --- /dev/null +++ b/src_wearable/Core/Buffer/RenderBuffer.h @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file RenderBuffer.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef RENDER_BUFFER_H +#define RENDER_BUFFER_H + +#include <memory> +#include <Ecore_Evas.h> +#include <Evas.h> +#include "IRenderBuffer.h" + +// forward declaration +struct livebox_buffer; + +// type definition +typedef struct livebox_buffer* BufferInfoPtr; +typedef void* BufferAddrPtr; + +#define EXPORT_CLASS __attribute__ ((visibility("default"))) + +class EXPORT_CLASS RenderBuffer: public IRenderBuffer { + public: + // IRenderBuffer Implementation + bool allocate(bool hwEnable = false); + bool reallocate(int width, int height); + bool free(); + void startCanvasUpdate(); + void stopCanvasUpdate(); + Evas_Object* getWindow(); + Evas_Object* getSnapshot(); + void setWebView(Evas_Object* webview){ m_webview = webview; }; + Evas_Object* getWebView(){ return m_webview; }; + Evas* getCanvas(); + + static void preRenderCallback(void* data, Evas* canvas, void* eventInfo); + static void postRenderCallback(void* data, Evas* canvas, void* eventInfo); + + virtual ~RenderBuffer(); + + protected: + void paintColor(unsigned int color); + + + // provided by derived class + virtual int getWidth() = 0; + virtual int getHeight() = 0; + virtual void setWidth(int width) = 0; + virtual void setHeight(int height) = 0; + virtual BufferInfoPtr acquireBuffer() = 0; + virtual void updateBuffer() = 0; + void* getBufferAddr() { return m_hwEnable ? m_bufferAddr : 0; } + RenderBuffer(); + Evas_Object* m_win; + Evas_Object* m_layout; + + private: + // callbacks + static void* allocateCallback(void* data, int size); + static void freeCallback(void* data, void *pix); + bool bufferAllocationForGLRendering(); + bool bufferAllocationForSWRendering(); + void bufferReAllocation(int width, int height); + + // members + Evas* m_canvas; + + BufferAddrPtr m_bufferAddr; + BufferInfoPtr m_bufferInfo; + bool m_hwEnable; + Evas_Object* m_webview; + +}; + +#endif diff --git a/src_wearable/Core/CMakeLists.txt b/src_wearable/Core/CMakeLists.txt new file mode 100644 index 0000000..39977e3 --- /dev/null +++ b/src_wearable/Core/CMakeLists.txt @@ -0,0 +1,88 @@ +# Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved +# +# Licensed under the Flora License, Version 1.1 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://floralicense.org/license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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) + +SET(TARGET_NAME ${TARGET_CORE}) +SET(TARGET_CORE_BUFFER web-provider-core-buffer) +SET(TARGET_CORE_VIEW web-provider-core-view) +SET(TARGET_CORE_UTIL web-provider-core-util) +SET(DEPS ${TARGET_NAME}_DEPS) + +PKG_CHECK_MODULES(${DEPS} + ecore + ewebkit2 + dlog + vconf + REQUIRED +) +ADD_DEFINITIONS(${${DEPS}_CFLAGS}) + +SET(SRCS + ${CMAKE_CURRENT_SOURCE_DIR}/Box.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/BoxLoadBalancer.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/BoxManager.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/BoxState.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/BoxUpdateTimer.cpp +) + +SET(HEADERS + ${${DEPS}_INCLUDE_DIRS} + ${CMAKE_CURRENT_SOURCE_DIR} +) +INCLUDE_DIRECTORIES(${HEADERS}) + +ADD_LIBRARY(${TARGET_NAME} SHARED ${SRCS}) + +SET_TARGET_PROPERTIES(${TARGET_NAME} PROPERTIES + COMPILE_FLAGS -fPIC + LINK_FLAGS "-Wl,--as-needed -Wl,--hash-style=both" +) + +SET_TARGET_PROPERTIES(${TARGET_NAME} + PROPERTIES + SOVERSION ${CMAKE_PROJECT_API_VERSION} + VERSION ${CMAKE_PROJECT_VERSION} +) + +TARGET_LINK_LIBRARIES(${TARGET_NAME} + ${${DEPS}_LIBRARIES} + "-Wl,--whole-archive" + ${TARGET_CORE_VIEW} + ${TARGET_CORE_BUFFER} + ${TARGET_CORE_UTIL} + "-Wl,--no-whole-archive" +) + +ADD_SUBDIRECTORY(Buffer) +ADD_SUBDIRECTORY(View) +ADD_SUBDIRECTORY(Util) + +INSTALL(TARGETS ${TARGET_NAME} + DESTINATION lib + PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE + GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE +) + +GET_FILENAME_COMPONENT(CURRENT_DIR_NAME ${CMAKE_CURRENT_SOURCE_DIR} NAME) + + +INSTALL_FILE(IBox.h include/${PROJECT_NAME}/${CURRENT_DIR_NAME}) +INSTALL_FILE(BoxData.h include/${PROJECT_NAME}/${CURRENT_DIR_NAME}) +INSTALL_FILE(IBoxManager.h include/${PROJECT_NAME}/${CURRENT_DIR_NAME}) +INSTALL_FILE(BoxManager.h include/${PROJECT_NAME}/${CURRENT_DIR_NAME}) +INSTALL_FILE(Platform.h include/${PROJECT_NAME}/${CURRENT_DIR_NAME}) +INSTALL_FILE(config.h include/${PROJECT_NAME}/${CURRENT_DIR_NAME}) +INSTALL_FILE(BoxLoadBalancer.h include/${PROJECT_NAME}/${CURRENT_DIR_NAME}) + diff --git a/src_wearable/Core/IBox.h b/src_wearable/Core/IBox.h new file mode 100644 index 0000000..6089da7 --- /dev/null +++ b/src_wearable/Core/IBox.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file IBox.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef I_BOX_H +#define I_BOX_H + +#include <string> +#include <memory> +#include <ctime> +#include <ewk_view.h> +#include <ewk_context.h> + +class IBox { + public: + // functions for lifecycle + virtual bool show() = 0; + virtual bool hide() = 0; + virtual bool resize(int width, int height) = 0; + virtual bool resume() = 0; + virtual bool pause(bool background) = 0; + virtual bool openPd(int width, int height, double x, double y) = 0; + virtual bool closePd() = 0; + virtual bool update(std::string& contentInfo) = 0; + virtual bool needToUpdate() = 0; + virtual void setNeedToUpdate() = 0; + virtual bool isPaused() = 0; + + // functions for getting/setting box's data by BoxManager + virtual bool changePeriod(float period) = 0; + virtual bool isCurrentTab() = 0; + virtual void setCurrent() = 0; + virtual BoxInfoPtr getBoxInfo() = 0; + + //virtual IBox& operator=(const IBox& rhs) = 0; + //virtual bool operator==(const IBox& rhs) const = 0; + //virtual bool operator!=(const IBox& rhs) const = 0; + virtual ~IBox() {}; +}; + +typedef std::shared_ptr<IBox> IBoxPtr; +typedef std::shared_ptr<Ewk_Context> EwkContextPtr; + +#endif //I_BOX_H diff --git a/src_wearable/Core/IBoxContext.h b/src_wearable/Core/IBoxContext.h new file mode 100644 index 0000000..8dfa2a7 --- /dev/null +++ b/src_wearable/Core/IBoxContext.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file IBoxContext.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef I_BOX_CONTEXT +#define I_BOX_CONTEXT + +#include "IBoxState.h" + +class IBoxContext { + public: + virtual void setState(IBoxStatePtr state) = 0; + virtual ~IBoxContext() {}; +}; + +typedef std::shared_ptr<IBoxContext> IBoxContextPtr; + +#endif // I_BOX_CONTEXT diff --git a/src_wearable/Core/IBoxManager.h b/src_wearable/Core/IBoxManager.h new file mode 100644 index 0000000..d441ed1 --- /dev/null +++ b/src_wearable/Core/IBoxManager.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file IBoxManager.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef I_BOX_MANAGER_H +#define I_BOX_MANAGER_H + +#include <string> +#include <Util/Noncopyable.h> +#include <Plugin/box_plugin_interface.h> +#include "BoxData.h" + +class IBoxManager: Noncopyable { + public: + virtual bool doCommand(const request_cmd_type, const BoxInfoPtr&) = 0; + virtual ~IBoxManager() {}; +}; + +typedef std::shared_ptr<IBoxManager> IBoxManagerPtr; + +#endif // I_BOX_MANAGER_H diff --git a/src_wearable/Core/IBoxState.h b/src_wearable/Core/IBoxState.h new file mode 100644 index 0000000..d798dc1 --- /dev/null +++ b/src_wearable/Core/IBoxState.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file IBoxState.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef I_BOX_STATE +#define I_BOX_STATE + +#include <memory> + +class IBoxState; +typedef std::shared_ptr<IBoxState> IBoxStatePtr; + +class IBoxState { + public: + virtual IBoxStatePtr permitShow() = 0; + virtual IBoxStatePtr permitHide() = 0; + virtual IBoxStatePtr permitResume() = 0; + virtual IBoxStatePtr permitPause() = 0; + virtual IBoxStatePtr permitOpenPd() = 0; + virtual IBoxStatePtr permitClosePd() = 0; + virtual IBoxStatePtr permitShutdown() = 0; + virtual void switchState() = 0; + virtual ~IBoxState() {}; +}; + +#endif // I_BOX_STATE diff --git a/src_wearable/Core/Platform.h b/src_wearable/Core/Platform.h new file mode 100644 index 0000000..c7e5077 --- /dev/null +++ b/src_wearable/Core/Platform.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file Platform.h + * @author Minhyung Ko (minhyung.ko@samsung.com) + */ + +#ifndef WEB_PROVIDER_PLATFORM_H +#define WEB_PROVIDER_PLATFORM_H + +// Use Features definition +// Use a particular optional platform service or third-party library +// +// Description : <text> +// <text> +// Author : <text>(<email>) - <date> +// #define USE_<DEPENDENT_MODULE_NAME>_<FEATURE_NAME> <value>(0 or 1) +#define USE(FEATURE) (defined WEB_PROVIDER_USE_##FEATURE && WEB_PROVIDER_USE_##FEATURE) + + +// Enable Features definition +// Turn on a specific feature of WRT +// +// Description : <text> +// <text> +// Author : <text>(<email>) - <date> +// #define ENABLE_<FEATURE_NAME> <value>(0 or 1) +#define ENABLE(FEATURE) (defined WEB_PROVIDER_ENABLE_##FEATURE && WEB_PROVIDER_ENABLE_##FEATURE) + +#define WEB_PROVIDER_ENABLE_BOX_LOAD_BALANCER 0 +#define WEB_PROVIDER_ENABLE_GL_RENDERING 1 +#define WEB_PROVIDER_ENABLE_SHOW_PRE_ICON 0 +#define WEB_PROVIDER_ENABLE_WEBKIT_UPVERSION 1 + +#endif // WEB_PROVIDER_PLATFORM_H diff --git a/src_wearable/Core/Util/CMakeLists.txt b/src_wearable/Core/Util/CMakeLists.txt new file mode 100644 index 0000000..11e14dc --- /dev/null +++ b/src_wearable/Core/Util/CMakeLists.txt @@ -0,0 +1,61 @@ +# Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved +# +# Licensed under the Flora License, Version 1.1 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://floralicense.org/license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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) + +SET(TARGET_NAME ${TARGET_CORE_UTIL}) +SET(DEPS ${TARGET_NAME}_DEPS) + +PKG_CHECK_MODULES(${DEPS} + dlog + REQUIRED +) +ADD_DEFINITIONS(${${DEPS}_CFLAGS}) + +SET(SRCS + ${CMAKE_CURRENT_SOURCE_DIR}/Log.cpp +) + +SET(HEADERS + ${${DEPS}_INCLUDE_DIRS} + ${CMAKE_CURRENT_SOURCE_DIR} +) + +INCLUDE_DIRECTORIES(${HEADERS}) + +ADD_LIBRARY(${TARGET_NAME} STATIC ${SRCS}) + +SET_TARGET_PROPERTIES(${TARGET_NAME} PROPERTIES + COMPILE_FLAGS -fPIC + LINK_FLAGS "-Wl,--as-needed -Wl,--hash-style=both" +) + +SET_TARGET_PROPERTIES(${TARGET_NAME} + PROPERTIES + SOVERSION ${CMAKE_PROJECT_API_VERSION} + VERSION ${CMAKE_PROJECT_VERSION} +) + +TARGET_LINK_LIBRARIES(${TARGET_NAME} + ${${DEPS}_LIBRARIES} +) + +INCLUDE_DIRECTORIES(${HEADERS}) +GET_FILENAME_COMPONENT(CURRENT_DIR_NAME ${CMAKE_CURRENT_SOURCE_DIR} NAME) +GET_FILENAME_COMPONENT(PARENT_DIR_ABSOLUTE_PATH ${CMAKE_CURRENT_SOURCE_DIR} PATH) +GET_FILENAME_COMPONENT(PARENT_DIR_NAME ${PARENT_DIR_ABSOLUTE_PATH} NAME) + +INSTALL_FILE(Noncopyable.h include/${PROJECT_NAME}/${PARENT_DIR_NAME}/${CURRENT_DIR_NAME}) +INSTALL_FILE(Log.h include/${PROJECT_NAME}/${PARENT_DIR_NAME}/${CURRENT_DIR_NAME}) +INSTALL_FILE(Util.h include/${PROJECT_NAME}/${PARENT_DIR_NAME}/${CURRENT_DIR_NAME}) diff --git a/src_wearable/Core/Util/ITimer.h b/src_wearable/Core/Util/ITimer.h new file mode 100644 index 0000000..2db0dae --- /dev/null +++ b/src_wearable/Core/Util/ITimer.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file ITimer.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef I_TIMER_H +#define I_TIMER_H + +#include <memory> + +class ITimer { + public: + virtual void start() = 0; + virtual void continueTimer(float period) = 0; + virtual void stop() = 0; + virtual void resume() = 0; + virtual void pause() = 0; + virtual void restart() = 0; + virtual void setPeriod(float period) = 0; + virtual float getPeriod() = 0; + virtual time_t getStartTime() = 0; + virtual bool isRunning() = 0; + + virtual ~ITimer() {}; +}; + +typedef std::shared_ptr<ITimer> ITimerPtr; + +#endif // I_TIMER_H diff --git a/src_wearable/Core/Util/Log.cpp b/src_wearable/Core/Util/Log.cpp new file mode 100644 index 0000000..34712ac --- /dev/null +++ b/src_wearable/Core/Util/Log.cpp @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file Log.cpp + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ diff --git a/src_wearable/Core/Util/Log.h b/src_wearable/Core/Util/Log.h new file mode 100644 index 0000000..ff649f7 --- /dev/null +++ b/src_wearable/Core/Util/Log.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file Log.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef LOG_H +#define LOG_H + +#include <dlog.h> +#include <string.h> + +#define FILE_NAME ((strrchr(__FILE__, '/') ? : __FILE__- 1) + 1) + +//#define LogW(fmt, arg...) LOGW( "[[32m%s:%d[0m:%s] " fmt "\n", __FILE__, __LINE__, __func__, ##arg) +//#define LogD(fmt, arg...) LOGD( "[[32m%s:%d[0m:%s] " fmt "\n", __FILE__, __LINE__, __func__, ##arg) +//#define LogE(fmt, arg...) LOGE( "[[32m%s:%d[0m:%s] " fmt "\n", __FILE__, __LINE__, __func__, ##arg) + +#define LogW(fmt, arg...) LOGW( fmt "\n", ##arg) +#define LogD(fmt, arg...) LOGD( fmt "\n", ##arg) +#define LogE(fmt, arg...) LOGE( fmt "\n", ##arg) +#endif // LOG_H diff --git a/src_wearable/Core/Util/Noncopyable.h b/src_wearable/Core/Util/Noncopyable.h new file mode 100644 index 0000000..accdd53 --- /dev/null +++ b/src_wearable/Core/Util/Noncopyable.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file Noncopyable.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef NONCOPYABLE_H +#define NONCOPYABLE_H + +class Noncopyable { + protected: + Noncopyable() {}; + ~Noncopyable() {}; + + private: + Noncopyable(const Noncopyable&); + Noncopyable& operator=(const Noncopyable&); +}; + +#endif // NONCOPYABLE_H diff --git a/src_wearable/Core/Util/Util.h b/src_wearable/Core/Util/Util.h new file mode 100644 index 0000000..b2c310d --- /dev/null +++ b/src_wearable/Core/Util/Util.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file Util.h + * @author Soo-Hyun Choi (sh9.choi@samsung.com) + */ +#ifndef UTIL_H +#define UTIL_H + +#define UNUSED_PARAM(expr) (void)(expr) + +#endif // UTIL_H diff --git a/src_wearable/Core/View/CMakeLists.txt b/src_wearable/Core/View/CMakeLists.txt new file mode 100644 index 0000000..17f32a6 --- /dev/null +++ b/src_wearable/Core/View/CMakeLists.txt @@ -0,0 +1,75 @@ +# Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved +# +# Licensed under the Flora License, Version 1.1 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://floralicense.org/license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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) + +SET(TARGET_NAME ${TARGET_CORE_VIEW}) +SET(TARGET_CORE_SERVICE web-provider-core-service) +SET(DEPS ${TARGET_NAME}_DEPS) + +PKG_CHECK_MODULES(${DEPS} + evas + eina + ewebkit2 + dlog + provider # this should be removed! + REQUIRED +) +ADD_DEFINITIONS(${${DEPS}_CFLAGS}) + +SET(SRCS + ${CMAKE_CURRENT_SOURCE_DIR}/WebView.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/PdHelper.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/RenderView.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/JsInterface.cpp +) + +SET(HEADERS + ${${DEPS}_INCLUDE_DIRS} + ${CMAKE_CURRENT_SOURCE_DIR} +) +INCLUDE_DIRECTORIES(${HEADERS}) + +ADD_LIBRARY(${TARGET_NAME} STATIC ${SRCS}) + +SET_TARGET_PROPERTIES(${TARGET_NAME} PROPERTIES + COMPILE_FLAGS -fPIC + LINK_FLAGS "-Wl,--as-needed -Wl,--hash-style=both" +) + +SET_TARGET_PROPERTIES(${TARGET_NAME} + PROPERTIES + SOVERSION ${CMAKE_PROJECT_API_VERSION} + VERSION ${CMAKE_PROJECT_VERSION} +) + +TARGET_LINK_LIBRARIES(${TARGET_NAME} + ${${DEPS}_LIBRARIES} + ${TARGET_CORE_SERVICE} +) + +ADD_SUBDIRECTORY(Service) + +GET_FILENAME_COMPONENT(CURRENT_DIR_NAME ${CMAKE_CURRENT_SOURCE_DIR} NAME) +GET_FILENAME_COMPONENT(PARENT_DIR_ABSOLUTE_PATH ${CMAKE_CURRENT_SOURCE_DIR} PATH) +GET_FILENAME_COMPONENT(PARENT_DIR_NAME ${PARENT_DIR_ABSOLUTE_PATH} NAME) + +INSTALL_FILE(IRenderView.h include/${PROJECT_NAME}/${PARENT_DIR_NAME}/${CURRENT_DIR_NAME}) +INSTALL_FILE(RenderView.h include/${PROJECT_NAME}/${PARENT_DIR_NAME}/${CURRENT_DIR_NAME}) +INSTALL_FILE(IPdHelper.h include/${PROJECT_NAME}/${PARENT_DIR_NAME}/${CURRENT_DIR_NAME}) +INSTALL_FILE(PdHelper.h include/${PROJECT_NAME}/${PARENT_DIR_NAME}/${CURRENT_DIR_NAME}) +INSTALL_FILE(IWebView.h include/${PROJECT_NAME}/${PARENT_DIR_NAME}/${CURRENT_DIR_NAME}) +INSTALL_FILE(WebView.h include/${PROJECT_NAME}/${PARENT_DIR_NAME}/${CURRENT_DIR_NAME}) +INSTALL_FILE(IJsInterface.h include/${PROJECT_NAME}/${PARENT_DIR_NAME}/${CURRENT_DIR_NAME}) +INSTALL_FILE(injection.js /usr/share/${PROJECT_NAME}) diff --git a/src_wearable/Core/View/IJsInterface.h b/src_wearable/Core/View/IJsInterface.h new file mode 100644 index 0000000..6de0776 --- /dev/null +++ b/src_wearable/Core/View/IJsInterface.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file IJsInterface.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef I_JS_INTERFACE_H +#define I_JS_INTERFACE_H + +#include <string> +#include <memory> + +class IJsInterface { + public: + virtual bool process(std::string& uri) = 0; + virtual ~IJsInterface() {}; +}; + +typedef std::shared_ptr<IJsInterface> IJsInterfacePtr; + +#endif //I_JS_INTERFACE_H diff --git a/src_wearable/Core/View/IPdHelper.h b/src_wearable/Core/View/IPdHelper.h new file mode 100644 index 0000000..b2f7db9 --- /dev/null +++ b/src_wearable/Core/View/IPdHelper.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file IPdHelper.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef I_PD_HELPER_H +#define I_PD_HELPER_H + +#include <Evas.h> +#include <memory> + +class IPdHelper { + public: + virtual void startOpen() = 0; + virtual void finishOpen(Evas_Object* child) = 0; + virtual void close() = 0; + virtual void setBoxWebView(Evas_Object* webview) = 0; + virtual void setPdWebView(Evas_Object* webview) = 0; + virtual Evas_Object* getBoxWebView() const = 0; + virtual Evas_Object* getPdWebView() const = 0; + virtual Evas* getPdCanvas() const = 0; + virtual bool isPdOpened() const = 0; +}; + +typedef std::shared_ptr<IPdHelper> IPdHelperPtr; + +#endif // I_PD_HELPER_H diff --git a/src_wearable/Core/View/IRenderView.h b/src_wearable/Core/View/IRenderView.h new file mode 100644 index 0000000..10e79ae --- /dev/null +++ b/src_wearable/Core/View/IRenderView.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file IRenderView.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef I_RENDER_VIEW_H +#define I_RENDER_VIEW_H + +#include <string> +#include <memory> +#include <Evas.h> + +class IRenderView { + public: + enum UrlType { + URL_TYPE_BOX, + URL_TYPE_PD + }; + virtual void show() = 0; + virtual void hide() = 0; + virtual void resize() = 0; + virtual void update() = 0; + virtual void pause() = 0; + virtual void resume() = 0; + virtual void openPd() = 0; + virtual void closePd() = 0; + virtual Evas_Object* getBoxWebView() = 0; + virtual Evas_Object* getPdWebView() = 0; + virtual ~IRenderView() {}; +}; + +typedef std::shared_ptr<IRenderView> IRenderViewPtr; + +#endif // I_RENDER_VIEW_H diff --git a/src_wearable/Core/View/IWebView.h b/src_wearable/Core/View/IWebView.h new file mode 100644 index 0000000..1260345 --- /dev/null +++ b/src_wearable/Core/View/IWebView.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file IWebView.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef I_WEB_VIEW_H +#define I_WEB_VIEW_H + +#include <string> +#include <memory> + +class IWebView { + public: + typedef void (*WebViewCallback)(void* data, void* eventInfo); + virtual bool show( + std::string& startUrl, int width, int height, + WebViewCallback didCreateBaseWebView, void* data) = 0; + virtual bool hide() = 0; + virtual bool suspend() = 0; + virtual bool resume() = 0; + virtual bool setBasicSetting(Evas_Object* webview) = 0; + virtual bool unsetBasicSetting(Evas_Object* webview) = 0; + + public: + virtual ~IWebView() {}; +}; + +typedef std::shared_ptr<IWebView> IWebViewPtr; + +#endif // I_WEB_VIEW_H diff --git a/src_wearable/Core/View/JsInterface.cpp b/src_wearable/Core/View/JsInterface.cpp new file mode 100755 index 0000000..d943c94 --- /dev/null +++ b/src_wearable/Core/View/JsInterface.cpp @@ -0,0 +1,243 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file JsInterface.cpp + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ + +#include <string.h> +#include <ctime> +#include <Core/BoxData.h> +#include <Core/Util/Log.h> +#include <Core/Util/Util.h> +#include "Service/AppControl.h" +#include "Service/PeriodChanger.h" +#include "Service/ScrollHolder.h" +#include "Service/MessageManager.h" +#include "JsInterface.h" + +using namespace Service; + +static const std::string BOX_SCHEME("box://"); +static const std::string BOX_SCHEME_RELOAD("box://reload"); +static const std::string BOX_SCHEME_CHANGE_PERIOD("box://change-period"); +static const std::string BOX_SCHEME_LAUNCH_BROWSER("box://launch-browser"); +static const std::string BOX_SCHEME_SEND_MESSAGE_TO_PD("box://send-message-to-pd"); +static const std::string BOX_SCHEME_SEND_MESSAGE_TO_BOX("box://send-message-to-box"); +static const std::string BOX_SCHEME_SCROLL_START("box://scroll-start"); +static const std::string BOX_SCHEME_SCROLL_STOP("box://scroll-stop"); + +static const std::string HTTP_SCHEME("http://"); +static const std::string HTTPS_SCHEME("https://"); + +JsInterface::JsInterface(RenderView* renderView, BoxInfoPtr boxInfo) + : m_renderView(renderView) + , m_boxInfo(boxInfo) +{ + LogD("enter"); +} + +JsInterface::~JsInterface() +{ + LogD("enter"); +} + +bool JsInterface::process(std::string& uri) +{ + LogD("enter"); + + if (!isBoxScheme(uri)) { + return false; + } + + if (!uri.compare(BOX_SCHEME_RELOAD)) { + return handleReload(); + } + + if (!uri.compare( + 0, + BOX_SCHEME_CHANGE_PERIOD.size(), + BOX_SCHEME_CHANGE_PERIOD)) + { + std::string key("period"); + std::string period = parse(uri, key); + if (period.empty()) { + return handleChangePeriod(); + } + + return handleChangePeriod(std::atof(period.c_str())); + } + + if (!uri.compare( + 0, + BOX_SCHEME_LAUNCH_BROWSER.size(), + BOX_SCHEME_LAUNCH_BROWSER)) + { + std::string key("url"); + std::string url = parse(uri, key); + return handleLaunchBrowser(url); + } + + if (!uri.compare( + 0, + BOX_SCHEME_SEND_MESSAGE_TO_BOX.size(), + BOX_SCHEME_SEND_MESSAGE_TO_BOX)) + { + std::string key("message"); + std::string message = parse(uri, key); + return handleSendMessage(MessageManager::TO_BOX, message); + } + + if (!uri.compare( + 0, + BOX_SCHEME_SEND_MESSAGE_TO_PD.size(), + BOX_SCHEME_SEND_MESSAGE_TO_PD)) + { + std::string key("message"); + std::string message = parse(uri, key); + return handleSendMessage(MessageManager::TO_PD, message); + } + + if (!uri.compare(BOX_SCHEME_SCROLL_START)) { + return handleScroll(true); + } + + if (!uri.compare(BOX_SCHEME_SCROLL_STOP)) { + return handleScroll(false); + } + + LogD("unknown box scheme protocol"); + return false; +} + +bool JsInterface::isBoxScheme(std::string& uri) +{ + LogD("enter"); + + if(!uri.compare(0, BOX_SCHEME.size(), BOX_SCHEME)) { + return true; + } + + return false; +} + +bool JsInterface::handleReload() +{ + LogD("enter"); + + m_renderView->update(); + return true; +} + +bool JsInterface::handleChangePeriod(float requestedPeriod) +{ + LogD("enter"); + + if (Service::PeriodChanger::isPopupOpened()) { + LogD("preiod popup is already opened!"); + return false; + } + + m_periodChanger = + Service::PeriodChanger::create( + m_boxInfo->boxId, m_boxInfo->instanceId, + m_boxInfo->period, requestedPeriod); + + return m_periodChanger->change(); +} + +bool JsInterface::handleLaunchBrowser(std::string& url) +{ + LogD("enter"); + + if (!url.compare(0, HTTP_SCHEME.size(), HTTP_SCHEME) || + !url.compare(0, HTTPS_SCHEME.size(), HTTPS_SCHEME)) + { + return Service::AppControl::launchBrowser(url); + } + + return false; +} + +bool JsInterface::handleSendMessage( + MessageManager::ReceiverType receiver, + std::string& message) +{ + LogD("enter"); + + // set webview of receiver + Evas_Object* webview; + switch (receiver) { + case MessageManager::TO_BOX: + webview = m_renderView->getBoxWebView(); + break; + case MessageManager::TO_PD: + webview = m_renderView->getPdWebView(); + break; + default: + LogD("not supported receiver"); + return false; + } + + return m_messageManager->send(webview, receiver, message); +} + +bool JsInterface::handleScroll(bool start) +{ + using namespace Service::ScrollHolder; + + LogD("enter"); + + holdHorizontalScroll(m_boxInfo->boxId, m_boxInfo->instanceId, start); + return true; +} + +std::string JsInterface::parse(std::string& uri, std::string& key) +{ + LogD("enter"); + + // TODO url parameter SHOULD be parsed using std::regex, not manually + std::string value(""); + + unsigned found = uri.find_first_of("?"); + if (found == std::string::npos) { + LogD("no query"); + return value; + } + + std::string query = std::string(uri, found + 1); + found = 0; + do { + LogD("enter\n"); + unsigned seperator = query.find_first_of("=", found + 1); + if (seperator == std::string::npos) { + LogD("no '=' character\n"); + break; + } + + unsigned next = query.find_first_of("@", found + 1); + if (!query.compare(found, key.size(), key)) { + LogD("key matched!\n"); + value = std::string(query, seperator + 1, next - seperator - 1); + break; + } + + found = next + 1; + } while (found && found != std::string::npos); + + LogD("URL query parsing result: key -> %s, value -> %s", key.c_str(), value.c_str()); + return value; +} diff --git a/src_wearable/Core/View/JsInterface.h b/src_wearable/Core/View/JsInterface.h new file mode 100755 index 0000000..187dac5 --- /dev/null +++ b/src_wearable/Core/View/JsInterface.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file JsInterface.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef JS_INTERFACE_H +#define JS_INTERFACE_H + +#include <string> +#include <map> +#include <Core/BoxData.h> +#include "Service/PeriodChanger.h" +#include "Service/MessageManager.h" +#include "RenderView.h" +#include "IJsInterface.h" + +using namespace Service; + +#define EXPORT_CLASS __attribute__ ((visibility("default"))) + +class EXPORT_CLASS JsInterface: public IJsInterface { + public: + static IJsInterfacePtr create(RenderView* renderView, BoxInfoPtr boxInfo) + { + return IJsInterfacePtr(new JsInterface(renderView, boxInfo)); + } + bool process(std::string& uri); + ~JsInterface(); + + private: + bool isBoxScheme(std::string& uri); + bool handleReload(); + bool handleChangePeriod(float requestedPeriod = -1.0f); + bool handleLaunchBrowser(std::string& url); + bool handleSendMessage( + MessageManager::ReceiverType receiver, + std::string& message); + bool handleScroll(bool start); + std::string parse(std::string& uri, std::string& key); + explicit JsInterface(RenderView* renderView, BoxInfoPtr boxInfo); + + // members for service + std::shared_ptr<PeriodChanger> m_periodChanger; + std::shared_ptr<MessageManager> m_messageManager; + RenderView* m_renderView; + BoxInfoPtr m_boxInfo; +}; + +#endif // JS_INTERFACE_H + diff --git a/src_wearable/Core/View/PdHelper.cpp b/src_wearable/Core/View/PdHelper.cpp new file mode 100644 index 0000000..ba57c8f --- /dev/null +++ b/src_wearable/Core/View/PdHelper.cpp @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file PdHelper.cpp + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#include <string> +#include <Evas.h> +#include <ewk_view.h> +#include <Core/Util/Log.h> +#include <Core/Util/Util.h> +#include "IRenderView.h" +#include "IPdHelper.h" +#include "PdHelper.h" + +PdHelper::PdHelper(RenderInfoPtr pdRenderInfo, std::string pdStartUrl) + : m_boxWebView() + , m_pdWebView() + , m_pdRenderInfo(pdRenderInfo) + , m_startUrl(pdStartUrl) + , m_opened(false) +{ +} + +PdHelper::~PdHelper() +{ +} + +void PdHelper::startOpen() +{ + LogD("enter"); + if (!m_boxWebView) { + return; + } + + //make javascript string for pd + std::string script = "var pdWindow = window.open(\""; + script += validateUrl(m_startUrl); + script += "\", \"_blank\");"; + + // execute javascript for opening new webview for pd + LogD("executed script: %s", script.c_str()); + ewk_view_script_execute( + m_boxWebView, script.c_str(), executeScriptCallback, this); +} + +void PdHelper::finishOpen(Evas_Object* child) +{ + LogD("enter"); + + // pd webview set and resize + m_pdWebView = child; + evas_object_resize(m_pdWebView, m_pdRenderInfo->width, m_pdRenderInfo->height); + m_opened = true; +} + +void PdHelper::close() +{ + LogD("enter"); +} + +void PdHelper::setBoxWebView(Evas_Object* webview) +{ + LogD("enter"); + m_boxWebView = webview; +} + +void PdHelper::setPdWebView(Evas_Object* webview) +{ + LogD("enter"); + m_pdWebView = webview; +} + +Evas_Object* PdHelper::getBoxWebView() const +{ + LogD("enter"); + return m_boxWebView; +} + +Evas_Object* PdHelper::getPdWebView() const +{ + LogD("enter"); + return m_pdWebView; +} + +Evas* PdHelper::getPdCanvas() const +{ + LogD("enter"); + return evas_object_evas_get(m_pdRenderInfo->window); +} + +bool PdHelper::isPdOpened() const +{ + LogD("enter"); + return m_opened; +} + +void PdHelper::didExecuteScript(Evas_Object* webview, std::string& result) +{ + LogD("enter"); + UNUSED_PARAM(webview); + LogD("javascript execution result: %s", result.c_str()); +} + +std::string PdHelper::validateUrl(std::string& url) +{ + LogD("enter"); + + if (url.empty()) { + return std::string(); + } + + if((!url.compare(0, 4, "http")) || + (!url.compare(0, 5, "https")) || + (!url.compare(0, 4, "file"))) + { + return url; + } + + std::string newUrl("file://"); + newUrl += url; + return newUrl; +} + +void PdHelper::executeScriptCallback( + Evas_Object* webview, const char* result, void* data) +{ + LogD("enter"); + + PdHelper* This = static_cast<PdHelper*>(data); + std::string resultStr(result ? result : "null"); + This->didExecuteScript(webview, resultStr); +} + diff --git a/src_wearable/Core/View/PdHelper.h b/src_wearable/Core/View/PdHelper.h new file mode 100644 index 0000000..63f9bb1 --- /dev/null +++ b/src_wearable/Core/View/PdHelper.h @@ -0,0 +1,69 @@ + +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file PdHelper.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ + +#ifndef PD_HELPER_H +#define PD_HELPER_H + +#include <string> +#include <Evas.h> +#include "RenderView.h" +#include "IPdHelper.h" + +#define EXPORT_CLASS __attribute__ ((visibility("default"))) + +class EXPORT_CLASS PdHelper: public IPdHelper { + public: + static IPdHelperPtr create( + RenderInfoPtr pdRenderInfo, + std::string pdStartUrl) + { + return IPdHelperPtr(new PdHelper(pdRenderInfo, pdStartUrl)); + } + virtual void startOpen(); + virtual void finishOpen(Evas_Object* child); + virtual void close(); + virtual void setBoxWebView(Evas_Object* webview); + virtual void setPdWebView(Evas_Object* webview); + virtual Evas_Object* getBoxWebView() const; + virtual Evas_Object* getPdWebView() const; + virtual Evas* getPdCanvas() const; + virtual bool isPdOpened() const; + virtual ~PdHelper(); + + private: + virtual void didExecuteScript(Evas_Object* webview, std::string& result); + + std::string validateUrl(std::string& url); + static void executeScriptCallback( + Evas_Object* webview, const char* result, void* data); + + PdHelper(RenderInfoPtr pdRenderInfo, std::string pdStartUrl); + + //members + Evas_Object* m_boxWebView; + Evas_Object* m_pdWebView; + RenderInfoPtr m_pdRenderInfo; + std::string m_startUrl; + bool m_opened; +}; + +#endif // PD_HELPER_H + diff --git a/src_wearable/Core/View/RenderView.cpp b/src_wearable/Core/View/RenderView.cpp new file mode 100644 index 0000000..78ad0d8 --- /dev/null +++ b/src_wearable/Core/View/RenderView.cpp @@ -0,0 +1,321 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file RenderView.cpp + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#include "config.h" +#include "RenderView.h" + +#include <string> +#include <sstream> +#include <functional> +#include <Ecore.h> +#include <ewk_view.h> +#include <Core/Buffer/IRenderBuffer.h> +#include <Core/Buffer/BoxRenderBuffer.h> +#include <Core/Buffer/PdRenderBuffer.h> +#include <Core/Util/Log.h> +#include <Core/Util/Util.h> +#include "JsInterface.h" +#include <sys/stat.h> + +using namespace std::placeholders; + +// This is used for informing context of box to web content as value of url parameter +static const std::string renderTypeCreate("create"); +static const std::string renderTypeResize("resize"); +static const std::string renderTypeOpenPd("pdopen"); +static const std::string renderTypeUpdate("update"); + +RenderView::RenderView(BoxInfoPtr boxInfo, bool hwEnable) + : m_boxInfo(boxInfo) + , m_boxBuffer() + , m_pdBuffer() + , m_jsInterface() + , m_lastShowBoxTime() +{ + + auto touchCallback = std::bind(RenderView::touchBoxCallback, _1, _2, this); + m_boxBuffer = BoxRenderBuffer::create(m_boxInfo, touchCallback); + m_boxBuffer->allocate(hwEnable); + m_jsInterface = JsInterface::create(this, m_boxInfo); +} + +RenderView::~RenderView() +{ +} + +void RenderView::show() +{ + LogD("enter"); + showInternal(renderTypeCreate); +} + +void RenderView::hide() +{ + LogD("enter"); + if (m_pdBuffer) { + closePd(); + } + m_boxBuffer->stopCanvasUpdate(); + hideBox(); + m_boxBuffer->free(); + m_boxBuffer.reset(); +} + +void RenderView::resize() +{ + LogD("enter"); + m_boxBuffer->reallocate( + m_boxInfo->boxWidth, m_boxInfo->boxHeight); + showInternal(renderTypeResize); +} + +void RenderView::update() +{ + LogD("enter"); + showInternal(renderTypeUpdate); +} + +void RenderView::resume() +{ + LogD("enter"); + resumeBox(); +} + +void RenderView::pause() +{ + LogD("enter"); + pauseBox(); +} + +void RenderView::openPd() +{ + LogD("enter"); + + auto touchCallback = std::bind(RenderView::touchPdCallback, _1, _2, this); + m_pdBuffer = PdRenderBuffer::create(m_boxInfo, touchCallback); + m_pdBuffer->allocate(); + m_pdBuffer->stopCanvasUpdate(); + showInternal(renderTypeOpenPd); + ecore_idler_add(startUpdateRenderBufferIdlerCallback, m_pdBuffer.get()); +} + +void RenderView::closePd() +{ + LogD("enter"); + if (m_pdBuffer) { + m_pdBuffer->stopCanvasUpdate(); + hidePd(); + m_pdBuffer->free(); + m_pdBuffer.reset(); + } +} + +Evas_Object* RenderView::getBoxWebView() +{ + LogD("enter"); + // this will be implemented by derived class + return NULL; +} + +Evas_Object* RenderView::getPdWebView() +{ + LogD("enter"); + // this will be implemented by derived class + return NULL; +} + +void RenderView::showBox(RenderInfoPtr boxRenderInfo) +{ + LogD("enter"); + UNUSED_PARAM(boxRenderInfo); + // this will be implemented by derived class +} + +void RenderView::hideBox() +{ + LogD("enter"); + // this will be implemented by derived class +} + +void RenderView::pauseBox() +{ + LogD("enter"); + // this will be implemented by derived class +} + +void RenderView::resumeBox() +{ + LogD("enter"); + // this will be implemented by derived class +} + +void RenderView::showPd(RenderInfoPtr pdRenderInfo, RenderInfoPtr boxRenderInfo) +{ + LogD("enter"); + UNUSED_PARAM(pdRenderInfo); + UNUSED_PARAM(boxRenderInfo); + // this will be implemented by derived class +} + +void RenderView::hidePd() +{ + LogD("enter"); + // this will be implemented by derived class +} + +IRenderBufferPtr RenderView::getBoxBuffer() const +{ + return m_boxBuffer; +} + +IRenderBufferPtr RenderView::getPdBuffer() const +{ + return m_pdBuffer; +} + +bool RenderView::processBoxScheme(std::string& uri) +{ + LogD("enter"); + return m_jsInterface->process(uri); +} + +void RenderView::didBoxTouched(int x, int y) +{ + UNUSED_PARAM(x); + UNUSED_PARAM(y); + // this will be implemented by derived class +} + +void RenderView::didPdTouched(int x, int y) +{ + UNUSED_PARAM(x); + UNUSED_PARAM(y); + // this will be implemented by derived class +} + +void RenderView::touchBoxCallback(int x, int y, RenderView* This) +{ + This->didBoxTouched(x, y); +} + +void RenderView::touchPdCallback(int x, int y, RenderView* This) +{ + This->didPdTouched(x, y); +} + +Eina_Bool RenderView::startUpdateRenderBufferIdlerCallback(void* data) +{ + LogD("enter"); + RenderBuffer* buffer = static_cast<RenderBuffer*>(data); + if (!buffer) { + LogD("no buffer"); + } else { + buffer->startCanvasUpdate(); + } + + return ECORE_CALLBACK_CANCEL; +} + +RenderInfoPtr RenderView::makeRenderInfo(const std::string& renderType, UrlType urlType) const +{ + LogD("enter"); + RenderInfoPtr renderInfo(new RenderInfo); + + std::ostringstream query; + + // add width, height, operation type + query << "?type=" << renderType; + + // set width, height + switch (urlType) { + case URL_TYPE_BOX: + renderInfo->window = m_boxBuffer->getWindow(); + renderInfo->width = m_boxInfo->boxWidth; + renderInfo->height = m_boxInfo->boxHeight; + break; + case URL_TYPE_PD: + renderInfo->window = m_pdBuffer->getWindow(); + renderInfo->width = m_boxInfo->pdWidth; + renderInfo->height = m_boxInfo->pdHeight; + break; + default: + LogD("error url type"); + return RenderInfoPtr(); + } + query << "&width=" << renderInfo->width << "&height=" << renderInfo->height; + + // if needed, set pd information + if (renderType == renderTypeOpenPd) { + // add position infomation of pd + query << "&pdopen-direction="; + if (m_boxInfo->pdY == 0.0f) { + query << "down"; + } else { + query << "up"; + } + + query << "&pdopen-arrow-xpos="; + query << static_cast<int>((m_boxInfo->pdX) * (m_boxInfo->pdWidth)); + + // add last update time & box's width, height + query << "&box-last-update-time=" << m_lastShowBoxTime; + query << "&box-width=" << m_boxInfo->boxWidth; + query << "&box-height=" << m_boxInfo->boxHeight; + } + + // add service content info passed from application + if (!m_boxInfo->appContentInfo.empty()) { + query << "&" << m_boxInfo->appContentInfo; + } + + // add content info passed from master provider + // this value can be different per box type + if (!m_boxInfo->contentInfo.empty()) { + query << "&" << m_boxInfo->contentInfo; + } + + LogD("default url param string: %s", query.str().c_str()); + renderInfo->defaultUrlParams = query.str(); + return renderInfo; +} + +void RenderView::showInternal(const std::string& renderType) +{ + LogD("enter"); + + if (renderType == renderTypeOpenPd) { + RenderInfoPtr pdRenderInfo = makeRenderInfo(renderType, URL_TYPE_PD); + RenderInfoPtr boxRenderInfo = makeRenderInfo(renderType, URL_TYPE_BOX); + showPd(pdRenderInfo, boxRenderInfo); + } else { + // set current time to lastest time for showing box + // this should be pre-executed before calling makeRenderInfo. + m_lastShowBoxTime = time(NULL); + RenderInfoPtr boxRenderInfo = makeRenderInfo(renderType, URL_TYPE_BOX); + showBox(boxRenderInfo); + } + + struct stat tmp; + + if (stat(WEB_PROVIDER_INSPECTOR_FILE_PATH, &tmp) == 0) { + unsigned int portnum = ewk_view_inspector_server_start( + getBoxWebView(), WEB_PROVIDER_INSPECTOR_PORT_NUMBER); + LogD("WEB_PROVIDER_INSPECTOR enabled port:%d",portnum); + } +} diff --git a/src_wearable/Core/View/RenderView.h b/src_wearable/Core/View/RenderView.h new file mode 100644 index 0000000..140b396 --- /dev/null +++ b/src_wearable/Core/View/RenderView.h @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file RenderView.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef RENDER_VIEW_H +#define RENDER_VIEW_H + +#include <string> +#include <memory> +#include <functional> +#include <Evas.h> +#include <Core/BoxData.h> +#include <Core/Buffer/IRenderBuffer.h> +#include "IJsInterface.h" +#include "IRenderView.h" + +#define EXPORT_CLASS __attribute__ ((visibility("default"))) + +typedef std::function<void(int, int)> TouchViewCallback; + +struct RenderInfo { + int width; + int height; + Evas_Object* window; + std::string defaultUrlParams; +}; + +typedef std::shared_ptr<RenderInfo> RenderInfoPtr; + +class EXPORT_CLASS RenderView: public IRenderView { + public: + static IRenderViewPtr create(BoxInfoPtr boxInfo) + { + return IRenderViewPtr(new RenderView(boxInfo)); + }; + void show(); + void hide(); + void resize(); + void update(); + void resume(); + void pause(); + void openPd(); + void closePd(); + virtual Evas_Object* getBoxWebView(); + virtual Evas_Object* getPdWebView(); + virtual ~RenderView(); + + protected: + virtual void showBox(RenderInfoPtr boxRenderInfo); + virtual void hideBox(); + virtual void pauseBox(); + virtual void resumeBox(); + virtual void showPd(RenderInfoPtr pdRenderInfo, RenderInfoPtr boxRenderInfo); + virtual void hidePd(); + virtual void didBoxTouched(int x, int y); + virtual void didPdTouched(int x, int y); + + // To be used by derived class + bool processBoxScheme(std::string& uri); + IRenderBufferPtr getBoxBuffer() const; + IRenderBufferPtr getPdBuffer() const; + + RenderView(BoxInfoPtr boxInfo, bool hwEnable = false); + RenderInfoPtr makeRenderInfo(const std::string& renderType, UrlType urlType) const; + + private: + void showInternal(const std::string& renderType); + static void touchBoxCallback(int x, int y, RenderView* This); + static void touchPdCallback(int x, int y, RenderView* This); + static Eina_Bool startUpdateRenderBufferIdlerCallback(void* data); + + // members + BoxInfoPtr m_boxInfo; + IRenderBufferPtr m_boxBuffer; + IRenderBufferPtr m_pdBuffer; + IJsInterfacePtr m_jsInterface; + // timestamp for last time of showing box. + time_t m_lastShowBoxTime; + + friend class BoxRenderBuffer; + friend class PdRenderBuffer; +}; + +#endif // RENDER_VIEW_H diff --git a/src_wearable/Core/View/Service/AppControl.cpp b/src_wearable/Core/View/Service/AppControl.cpp new file mode 100644 index 0000000..761dd93 --- /dev/null +++ b/src_wearable/Core/View/Service/AppControl.cpp @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file LaunchBrowser.cpp + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ + +#include <string> +#include <app_service.h> +#include <Core/Util/Log.h> +#include "AppControl.h" + +namespace Service { +namespace AppControl { + +bool launchBrowser(std::string& url) +{ + LogD("enter"); + + service_h handle = NULL; + int ret = SERVICE_ERROR_NONE; + + ret = service_create(&handle); + if (ret != SERVICE_ERROR_NONE) { + LogD("failed to create service"); + return false; + } + + ret = service_set_operation(handle, SERVICE_OPERATION_VIEW); + if (ret != SERVICE_ERROR_NONE) { + LogD("failed to set operation"); + service_destroy(handle); + return false; + } + + ret = service_set_uri(handle, url.c_str()); + if (ret != SERVICE_ERROR_NONE) { + LogD("failed to set url"); + service_destroy(handle); + return false; + } + + ret = service_send_launch_request(handle, NULL, NULL); + if (ret != SERVICE_ERROR_NONE) { + LogD("failed to request launch"); + service_destroy(handle); + return false; + } + + LogD("success to launch browser: %s", url.c_str()); + service_destroy(handle); + + return true; +} + +bool launchDownloader(std::string& url, std::string& cookie) +{ + LogD("enter"); + + service_h handle = NULL; + int ret = SERVICE_ERROR_NONE; + + if (url.empty()) { + LogD("invalid arguments"); + return false; + } + + ret = service_create(&handle); + if (ret != SERVICE_ERROR_NONE) { + LogD("failed to create service"); + return false; + } + + ret = service_set_operation(handle, SERVICE_OPERATION_DOWNLOAD); + if (ret != SERVICE_ERROR_NONE) { + LogD("failed to set operation"); + service_destroy(handle); + return false; + } + + ret = service_set_uri(handle, url.c_str()); + if (ret != SERVICE_ERROR_NONE) { + LogD("failed to set url"); + service_destroy(handle); + return false; + } + + if (!cookie.empty()) { + ret = service_add_extra_data(handle, "cookie", cookie.c_str()); + if (ret != SERVICE_ERROR_NONE) { + LogD("failed to set cookie"); + service_destroy(handle); + return false; + } + } + + ret = service_send_launch_request(handle, NULL, NULL); + if (ret != SERVICE_ERROR_NONE) { + LogD("failed to request launch"); + service_destroy(handle); + return false; + } + + LogD("success to launch downloader"); + service_destroy(handle); + + return true; +} + +} // AppControl +} // Service diff --git a/src_wearable/Core/View/Service/AppControl.h b/src_wearable/Core/View/Service/AppControl.h new file mode 100644 index 0000000..5693873 --- /dev/null +++ b/src_wearable/Core/View/Service/AppControl.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file AppControl.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ + +#include <string> + +namespace Service { +namespace AppControl { + +bool launchBrowser(std::string& url); +bool launchDownloader(std::string& url, std::string& cookie); + +} +} // Service diff --git a/src_wearable/Core/View/Service/CMakeLists.txt b/src_wearable/Core/View/Service/CMakeLists.txt new file mode 100755 index 0000000..ad8fa36 --- /dev/null +++ b/src_wearable/Core/View/Service/CMakeLists.txt @@ -0,0 +1,72 @@ +# Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved +# +# Licensed under the Flora License, Version 1.1 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://floralicense.org/license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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) + +SET(TARGET_NAME ${TARGET_CORE_SERVICE}) +SET(DEPS ${TARGET_NAME}_DEPS) + +PKG_CHECK_MODULES(${DEPS} + dlog + capi-appfw-application + livebox-service + evas + eina + ecore-x + elementary + efl-assist + provider + ecore + REQUIRED +) +ADD_DEFINITIONS(${${DEPS}_CFLAGS}) + +SET(SRCS + ${CMAKE_CURRENT_SOURCE_DIR}/AppControl.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/PeriodChanger.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/ScrollHolder.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/MessageManager.cpp +) + +SET(HEADERS + ${${DEPS}_INCLUDE_DIRS} + ${CMAKE_CURRENT_SOURCE_DIR} +) +INCLUDE_DIRECTORIES(${HEADERS}) + +ADD_LIBRARY(${TARGET_NAME} STATIC ${SRCS}) + +SET_TARGET_PROPERTIES(${TARGET_NAME} PROPERTIES + COMPILE_FLAGS -fPIC + LINK_FLAGS "-Wl,--as-needed -Wl,--hash-style=both" +) + +SET_TARGET_PROPERTIES(${TARGET_NAME} + PROPERTIES + SOVERSION ${CMAKE_PROJECT_API_VERSION} + VERSION ${CMAKE_PROJECT_VERSION} +) + +TARGET_LINK_LIBRARIES(${TARGET_NAME} + ${${DEPS}_LIBRARIES} +) + +GET_FILENAME_COMPONENT(CURRENT_DIR_NAME ${CMAKE_CURRENT_SOURCE_DIR} NAME) +GET_FILENAME_COMPONENT(PARENT_DIR_ABSOLUTE_PATH ${CMAKE_CURRENT_SOURCE_DIR} PATH) +GET_FILENAME_COMPONENT(PARENT_DIR_NAME ${PARENT_DIR_ABSOLUTE_PATH} NAME) + +INSTALL_FILE(PeriodChanger.h include/${PROJECT_NAME}/${PARENT_DIR_NAME}/${CURRENT_DIR_NAME}) +INSTALL_FILE(MessageManager.h include/${PROJECT_NAME}/${PARENT_DIR_NAME}/${CURRENT_DIR_NAME}) +INSTALL_FILE(ScrollHolder.h include/${PROJECT_NAME}/${PARENT_DIR_NAME}/${CURRENT_DIR_NAME}) +INSTALL_FILE(AppControl.h include/${PROJECT_NAME}/${PARENT_DIR_NAME}/${CURRENT_DIR_NAME}) diff --git a/src_wearable/Core/View/Service/MessageManager.cpp b/src_wearable/Core/View/Service/MessageManager.cpp new file mode 100755 index 0000000..3199d86 --- /dev/null +++ b/src_wearable/Core/View/Service/MessageManager.cpp @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file MessageMenager.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ + +#include <string> +#include <Evas.h> +#include <Eina.h> +#include <ewk_view.h> +#include <Core/Util/Log.h> +#include <Core/Util/Util.h> +#include "MessageManager.h" + +namespace Service { + +static const std::string jsFireWindowEventFunction("webprovider.fireAppWidgetEvent"); +static const std::string jsPdMessageEvent("pdmessage"); +static const std::string jsBoxMessageEvent("boxmessage"); + +MessageManager::MessageManager() +{ + LogD("enter"); +} + +MessageManager::~MessageManager() +{ + LogD("enter"); +} + +bool MessageManager::send(Evas_Object* webview, ReceiverType receiver, std::string& message) +{ + LogD("enter"); + + std::string eventName; + if(!webview) { + return false; + } + // set message event name triggered by receiver + switch (receiver) { + case TO_BOX: + eventName = jsPdMessageEvent; + break; + case TO_PD: + eventName = jsBoxMessageEvent; + break; + default: + return false; + } + + std::string script = jsFireWindowEventFunction; + script += "(\""; + script += eventName; + script += "\", \""; + script += message; + script +="\");"; + LogD("calling javascript: %s", script.c_str()); + + // execute js code for sending message + if (EINA_FALSE == ewk_view_script_execute( + webview, script.c_str(), executeScriptCallback, this)) { + LogD("ewk_view_script_execute fail."); + } + + return true; +} + +void MessageManager::executeScriptCallback( + Evas_Object* webview, const char* result, void* data) +{ + LogD("enter"); + UNUSED_PARAM(webview); + UNUSED_PARAM(data); + + std::string resultStr(result ? result : "null"); + LogD("result: %s", resultStr.c_str()); +} +} // Service diff --git a/src_wearable/Core/View/Service/MessageManager.h b/src_wearable/Core/View/Service/MessageManager.h new file mode 100644 index 0000000..d19b69d --- /dev/null +++ b/src_wearable/Core/View/Service/MessageManager.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file MessageManager.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ + +#ifndef MESSAGE_MANAGER_H +#define MESSAGE_MANAGER_H + +#include <string> +#include <memory> +#include <Evas.h> + +namespace Service { + +class MessageManager; +typedef std::shared_ptr<MessageManager> MessageManagerPtr; + +class MessageManager { + public: + enum ReceiverType { + TO_BOX, + TO_PD + }; + + static MessageManagerPtr create() { + return MessageManagerPtr(new MessageManager()); + } + bool send(Evas_Object* webview, ReceiverType receiver, std::string& message); + ~MessageManager(); + + private: + static void executeScriptCallback( + Evas_Object* webview, const char* result, void* data); + MessageManager(); +}; +} // Service + +#endif // MESSAGE_MANAGER_H diff --git a/src_wearable/Core/View/Service/PeriodChanger.cpp b/src_wearable/Core/View/Service/PeriodChanger.cpp new file mode 100755 index 0000000..856191b --- /dev/null +++ b/src_wearable/Core/View/Service/PeriodChanger.cpp @@ -0,0 +1,276 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file PeriodChanger.cpp + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ + +#include <string> +#include <Evas.h> +#include <Ecore_X.h> +#include <Ecore.h> +#include <Elementary.h> +#include <efl_assist.h> +#include <livebox-service.h> +#include <Core/Util/Log.h> +#include <Core/Util/Util.h> +#include "PeriodChanger.h" + +#define UPDATE_PERIOD_MIN 1800.0f +#define UPDATE_PERIOD_HOUR 60.0 * 60.0 +#define U_(str) dgettext("web-provider", str) + +namespace Service { + +Evas_Object* PeriodChanger::s_window = NULL; +bool PeriodChanger::s_isPopupOpened = false; + +static const char * const TEXT_POPUP_TITLE = "IDS_BR_HEADER_AUTO_REFRESH"; +static const char * const TEXT_POPUP_CANCEL_BUTTON = "IDS_ST_BUTTON_CANCEL"; +static const char * const TEXT_POPUP_UPDATE_PERIOD_1 ="IDS_ST_BODY_1_HOUR"; +static const char * const TEXT_POPUP_UPDATE_PERIOD_3 ="IDS_ST_BODY_3HOURS"; +static const char * const TEXT_POPUP_UPDATE_PERIOD_6 ="IDS_ST_BODY_6_HOURS_TMO"; +static const char * const TEXT_POPUP_UPDATE_PERIOD_12 ="IDS_ST_BODY_12_HOURS"; +static const char * const TEXT_POPUP_UPDATE_PERIOD_NEVER ="IDS_BR_OPT_NEVER"; +static const char * const MO_INSTALL_DIR = "/usr/share/res/locale"; +static const char * const MO_PROJECT_NAME = "web-provider"; + +PeriodChanger::PeriodChanger( + std::string& boxId, std::string& instanceId, + double currentPeriod, double requestedPeriod) + : m_boxId(boxId) + , m_instanceId(instanceId) + , m_currentPeriod(currentPeriod) + , m_requestedPeriod(requestedPeriod) + , m_hour() +{ + LogD("enter"); +} + +PeriodChanger::~PeriodChanger() +{ + LogD("enter"); +} + +bool PeriodChanger::change() +{ + LogD("enter"); + + if (m_requestedPeriod < 0) { + showPeriodPopup(); + return true; + } + + double newPeriod; + if (m_requestedPeriod == 0) { + newPeriod = 0.0; + } else if (m_requestedPeriod > 0) { + if (m_requestedPeriod >= UPDATE_PERIOD_MIN) { + newPeriod = m_requestedPeriod; + } else { + newPeriod = UPDATE_PERIOD_MIN; + } + } else { + LogD("negative value can't be handled here"); + newPeriod = 0.0; + } + + // after selecting one among period list, the following should be executed + return requestToPlatform(newPeriod); +} + +void PeriodChanger::showPeriodPopup() +{ + LogD("enter"); + + Evas_Object* window = createWindow(); + Evas_Object* periodList = elm_list_add(window); + + if (!periodList) { + LogD("failed to add elm_list_add"); + } + elm_list_mode_set(periodList, ELM_LIST_EXPAND); + bindtextdomain(MO_PROJECT_NAME, MO_INSTALL_DIR); + setPopupListData(); + // TODO Language ID should be used, not static string + for(unsigned int i = 0 ; i < sizeof(m_hour) / sizeof(PopupListData); i++) { + m_hour[i].radio = elm_radio_add(periodList); + elm_radio_state_value_set(m_hour[i].radio, + m_currentPeriod == m_hour[i].newPeriod ? EINA_FALSE : EINA_TRUE); + elm_list_item_append(periodList, + m_hour[i].period, + m_hour[i].radio, + NULL, + selectPeriodCallback, &m_hour[i]); + } + + // create popup + Evas_Object *popup = elm_popup_add(window); + if (!popup) { + LogD("failed to add elm_popup_add"); + return; + } + elm_object_style_set(popup, "popup-item list"); + evas_object_size_hint_weight_set(popup, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + elm_object_part_text_set(popup, "title,text", U_(TEXT_POPUP_TITLE)); + elm_object_content_set(popup, periodList); + evas_object_show(popup); + + // register back key callback + ea_object_event_callback_add( + popup, EA_CALLBACK_BACK, + pressHardwareBackKeyCallback, this); +} + +void PeriodChanger::destroyPeriodPopup(Evas_Object *obj) +{ + LogD("enter"); + Evas_Object* parent = elm_object_parent_widget_get(obj); + Evas_Object* popup = elm_popup_add(parent); + while (parent) { + const char* type = elm_object_widget_type_get(parent); + if (type && !strcmp(type, elm_object_widget_type_get(popup))) { + evas_object_del(parent); + break; + } + parent = elm_object_parent_widget_get(parent); + } + + // register back key callback + ea_object_event_callback_del(popup, EA_CALLBACK_BACK, pressHardwareBackKeyCallback); + evas_object_del(popup); + destroyWindow(); +} + +void PeriodChanger::setPopupListData() +{ + LogD("enter"); + + m_hour[0].periodChanger = this; + m_hour[0].newPeriod = 1.0 * UPDATE_PERIOD_HOUR; + m_hour[0].period = U_(TEXT_POPUP_UPDATE_PERIOD_1); + + m_hour[1].periodChanger = this; + m_hour[1].newPeriod = 3.0 * UPDATE_PERIOD_HOUR; + m_hour[1].period = U_(TEXT_POPUP_UPDATE_PERIOD_3); + + m_hour[2].periodChanger = this; + m_hour[2].newPeriod = 6.0 * UPDATE_PERIOD_HOUR; + m_hour[2].period = U_(TEXT_POPUP_UPDATE_PERIOD_6); + + m_hour[3].periodChanger = this; + m_hour[3].newPeriod = 12.0 * UPDATE_PERIOD_HOUR; + m_hour[3].period = U_(TEXT_POPUP_UPDATE_PERIOD_12); + + m_hour[4].periodChanger = this; + m_hour[4].newPeriod = 0.0; + m_hour[4].period = U_(TEXT_POPUP_UPDATE_PERIOD_NEVER); + +} + +bool PeriodChanger::requestToPlatform(double newPeriod) +{ + int ret = livebox_service_change_period( + m_boxId.c_str(), m_instanceId.c_str(), newPeriod); + + if (ret < 0) { + LogD("during update period, error occurs"); + return false; + } + + LogD("Instance's period is set to %f", newPeriod); + return true; +} + + +Evas_Object* PeriodChanger::createWindow() +{ + LogD("enter"); + + if (s_window) { + evas_object_show(s_window); + elm_win_raise(s_window); + return s_window; + } + + s_window = elm_win_add(NULL, "web-provider-popup", ELM_WIN_BASIC); + elm_win_alpha_set(s_window, EINA_TRUE); + elm_win_title_set(s_window, "change update period"); + elm_win_borderless_set(s_window, EINA_TRUE); + + int width = 0; + int height = 0; + ecore_x_window_size_get(ecore_x_window_root_first_get(), &width, &height); + evas_object_resize(s_window, width, height); + elm_win_indicator_mode_set(s_window, ELM_WIN_INDICATOR_SHOW); + + evas_object_color_set(s_window, 255, 255, 255, 0); + evas_object_show(s_window); + s_isPopupOpened = true; + return s_window; +} + +void PeriodChanger::destroyWindow() +{ + LogD("enter"); + + if (!s_window) { + return; + } + evas_object_del(s_window); + s_window = NULL; + s_isPopupOpened = false; +} + +void PeriodChanger::selectPeriodCallback(void *data, Evas_Object *obj, void *event_info) +{ + LogD("enter"); + UNUSED_PARAM(obj); + UNUSED_PARAM(event_info); + + PopupListData* popupData = static_cast<PopupListData*>(data); + + LogD("Update period is set to %f", popupData->newPeriod); + popupData->periodChanger->requestToPlatform(popupData->newPeriod); + ecore_idler_add(popupDestroyIdlerCallback, popupData); +} + +void PeriodChanger::cancelButtonCallback(void *data, Evas_Object *obj, void *event_info) +{ + LogD("enter"); + UNUSED_PARAM(event_info); + + PeriodChanger* This = static_cast<PeriodChanger*>(data); + This->destroyPeriodPopup(obj); +} + +void PeriodChanger::pressHardwareBackKeyCallback(void *data, Evas_Object *obj, void *event_info) +{ + LogD("enter"); + UNUSED_PARAM(event_info); + + PeriodChanger* This = static_cast<PeriodChanger*>(data); + This->destroyPeriodPopup(obj); +} + +Eina_Bool PeriodChanger::popupDestroyIdlerCallback(void *data) +{ + LogD("enter"); + PopupListData* popupData = static_cast<PopupListData*>(data); + popupData->periodChanger->destroyPeriodPopup(popupData->radio); + return ECORE_CALLBACK_CANCEL; +} +} // Service diff --git a/src_wearable/Core/View/Service/PeriodChanger.h b/src_wearable/Core/View/Service/PeriodChanger.h new file mode 100755 index 0000000..b8902b0 --- /dev/null +++ b/src_wearable/Core/View/Service/PeriodChanger.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file PeriodChanger.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef PERIOD_CHNAGER_H +#define PERIOD_CHNAGER_H + +#include <string> +#include <memory> +#include <Evas.h> + +namespace Service { +class PeriodChanger; +typedef std::shared_ptr<PeriodChanger> PeriodChangerPtr; + +class PeriodChanger { + public: + static PeriodChangerPtr create( + std::string& boxId, std::string& instanceId, + double currentPeriod, double requestedPeriod) + { + return PeriodChangerPtr( + new PeriodChanger(boxId, instanceId, currentPeriod, requestedPeriod)); + } + bool change(); + static bool isPopupOpened() { return s_isPopupOpened; }; + ~PeriodChanger(); + + private: + void showPeriodPopup(); + void destroyPeriodPopup(Evas_Object *obj); + void setPopupListData(); + bool requestToPlatform(double newPeriod); + static Evas_Object* createWindow(); + static void destroyWindow(); + + static void selectPeriodCallback(void *data, Evas_Object *obj, void *event_info); + static void cancelButtonCallback(void *data, Evas_Object *obj, void *event_info); + static void pressHardwareBackKeyCallback(void *data, Evas_Object *obj, void *event_info); + static Eina_Bool popupDestroyIdlerCallback(void *data); + + PeriodChanger( + std::string& boxId, std::string& instanceId, + double currentPeriod, double requestedPeriod); + + static Evas_Object* s_window; + std::string m_boxId; + std::string m_instanceId; + float m_currentPeriod; + float m_requestedPeriod; + static bool s_isPopupOpened; + + struct PopupListData { + PeriodChanger* periodChanger; + double newPeriod; + const char* period; + Evas_Object* radio; + }; + + PopupListData m_hour[5]; +}; +} // Service + +#endif // PERIOD_CHNAGER_H diff --git a/src_wearable/Core/View/Service/ScrollHolder.cpp b/src_wearable/Core/View/Service/ScrollHolder.cpp new file mode 100644 index 0000000..3435ff7 --- /dev/null +++ b/src_wearable/Core/View/Service/ScrollHolder.cpp @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file ScrollHolder.cpp + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ + +#include <string> +#include <provider.h> +#include <Core/Util/Log.h> + +namespace Service { +namespace ScrollHolder { + +void holdHorizontalScroll(std::string& boxId, std::string& instanceId, bool start) +{ + LogD("enter"); + + if (start) { + LogD("scroll start"); + provider_send_hold_scroll(boxId.c_str(), instanceId.c_str(), 1); + } else { + LogD("scroll stop"); + provider_send_hold_scroll(boxId.c_str(), instanceId.c_str(), 0); + } +} + +} // AppControl +} // Service diff --git a/src_wearable/Core/View/Service/ScrollHolder.h b/src_wearable/Core/View/Service/ScrollHolder.h new file mode 100644 index 0000000..a7373b7 --- /dev/null +++ b/src_wearable/Core/View/Service/ScrollHolder.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file ScrollHolder.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ + +#include <string> + +namespace Service { +namespace ScrollHolder { + +void holdHorizontalScroll(std::string& boxId, std::string& instanceId, bool start); + +} +} // Service diff --git a/src_wearable/Core/View/WebView.cpp b/src_wearable/Core/View/WebView.cpp new file mode 100755 index 0000000..5e4987d --- /dev/null +++ b/src_wearable/Core/View/WebView.cpp @@ -0,0 +1,904 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file WebView.cpp + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#include "WebView.h" + +#include "config.h" + +#include <sstream> +#include <string> +#include <fstream> +#include <streambuf> +#include <Evas.h> +#include <Eina.h> +#include <ewk_context.h> +#include <ewk_view.h> +#include <ewk_policy_decision.h> +#include <ewk_console_message.h> +#include <Core/Util/Log.h> +#include <Core/Util/Util.h> +#include "Service/AppControl.h" + +// injection javascript file regarding creating js object used by box and pd +static const std::string injectionFile("/usr/share/web-provider/injection.js"); +static const char* consoleMessageDlogTag = "ConsoleMessage"; + +std::map<const std::string, const Evas_Smart_Cb> WebView::m_smartCallbacksMap = +{ + {"load,started", WebView::loadStartedCallback}, + {"load,finished", WebView::loadFinishedCallback}, + {"title,changed", WebView::titleChangedCallback}, + {"uri,changed", WebView::uriChangedCallback}, + {"load,progress", WebView::loadProgressCallback}, + {"load,progress,finished", WebView::loadProgressFinishedCallback}, + {"process,crashed", WebView::processCrashedCallback}, + {"create,window", WebView::createWindowCallback}, + {"close,window", WebView::closeWindowCallback}, + {"policy,navigation,decide", WebView::policyNavigationDecideCallback}, + {"policy,newwindow,decide", WebView::policyNewWindowDecideCallback}, + {"policy,response,decide", WebView::pageResponseDecideCallback}, + {"contextmenu,customize", WebView::contextmenuCustomizeCallback}, + {"form,submit", WebView::formSubmitCallback}, + {"request,geolocation,permission", WebView::geolocationPermissionRequestCallback}, + {"notification,show", WebView::notificationShowCallback}, + {"notification,cancel", WebView::notificationCancelCallback}, + {"notification,permission,request", WebView::notificationPermissionRequestCallback}, + {"database,quota,exceeded", WebView::databaseUsagePermissionRequestCallback}, + {"filesystem,permission,request", WebView::fileSystemPermissionRequestCallback}, + {"fullscreen,enterfullscreen", WebView::enterFullscreenCallback}, + {"fullscreen,exitfullscreen", WebView::exitFullscreenCallback}, + {"inputmethod,changed", WebView::imeChangedCallback}, + {"editorclient,ime,opened", WebView::imeOpenedCallback}, + {"editorclient,ime,closed", WebView::imeClosedCallback}, + {"usermedia,permission,request", WebView::usermediaPermissionRequestCallback}, + {"protocolhandler,registration,requested", WebView::protocolHandlerRegistrationCallback}, + {"protocolhandler,isregistered", WebView::protocolHandlerIsRegisteredCallback}, + {"protocolhandler,unregistration,requested", WebView::protocolHandlerUnregistrationCallback}, + {"contenthandler,registration,requested", WebView::contentHandlerRegistrationCallback}, + {"contenthandler,isregistered", WebView::contentHandlerIsRegisteredCallback}, + {"contenthandler,unregistration,requested", WebView::contentHandlerUnregistrationCallback}, + {"request,certificate,confirm", WebView::certificateConfirmRequestCallback}, + {"console,message", WebView::consoleMessageCallback} +}; + +WebView::WebView(Evas_Object* win, Ewk_Context* ewkContext) + : m_topWebview(NULL) + , m_win(win) + , m_ewkContext(ewkContext) +{ +} + +WebView::~WebView() +{ +} + +bool WebView::show( + std::string& startUrl, int width, int height, + WebViewCallback didCreateBaseWebView, void* data) +{ + LogD("enter"); + if (!m_topWebview) { + m_topWebview = ewk_view_add_with_context( + evas_object_evas_get(m_win), m_ewkContext); + if (!setBasicSetting(m_topWebview)) { + return false; + } + } + + // inform base webview to caller + if (didCreateBaseWebView) { + didCreateBaseWebView(data, static_cast<void*>(m_topWebview)); + } + + // check scheme of url + std::string url = validateUrl(startUrl); + LogD("load: %s", url.c_str()); + ewk_view_url_set(m_topWebview, url.c_str()); + + evas_object_resize(m_topWebview, width, height); + evas_object_show(m_topWebview); + + return true; +} + +bool WebView::hide() +{ + LogD("enter"); + + // TODO If created webviews are managed by WebView Class, + // add code regarding created all webviews + if (!unsetBasicSetting(m_topWebview)) { + return false; + } + if(!m_topWebview) { + return false; + } + for (auto it = m_smartCallbacksMap.begin(); + it != m_smartCallbacksMap.end(); it++) { + evas_object_smart_callback_del( + m_topWebview, it->first.c_str(), it->second); + } + + evas_object_del(m_topWebview); + m_topWebview = NULL; + + return true; +} + +bool WebView::suspend() +{ + LogD("enter"); + ewk_view_page_visibility_state_set( + m_topWebview, EWK_PAGE_VISIBILITY_STATE_HIDDEN, EINA_FALSE); + ewk_view_suspend(m_topWebview); + return true; +} + +bool WebView::resume() +{ + LogD("enter"); + ewk_view_resume(m_topWebview); + ewk_view_page_visibility_state_set( + m_topWebview, EWK_PAGE_VISIBILITY_STATE_VISIBLE, EINA_FALSE); + return true; +} + +bool WebView::setBasicSetting(Evas_Object* webview) +{ + LogD("enter"); + + if (!webview) { + return false; + } + + for (auto it = m_smartCallbacksMap.begin(); + it != m_smartCallbacksMap.end(); it++) { + evas_object_smart_callback_add( + webview, it->first.c_str(), it->second, this); + } + + // set specific features + Ewk_Settings* setting = ewk_view_settings_get(webview); + // set user agent like WRT, or Browser? + // ewk_view_user_agent_set(webview, "some_ua_string"); + ewk_settings_plugins_enabled_set(setting, EINA_TRUE); + ewk_settings_javascript_enabled_set(setting, EINA_TRUE); + ewk_settings_loads_images_automatically_set(setting, EINA_TRUE); + ewk_settings_auto_fitting_set(setting, EINA_FALSE); +#if !ENABLE(WEBKIT_UPVERSION) + ewk_settings_default_keypad_enabled_set(setting, EINA_FALSE); +#endif + ewk_settings_text_selection_enabled_set(setting, EINA_FALSE); + + // set visibility + ewk_view_page_visibility_state_set( + webview, EWK_PAGE_VISIBILITY_STATE_VISIBLE, EINA_TRUE); + + evas_object_color_set(webview, 0, 0, 0, 1); + ewk_view_use_settings_font(webview); + + return true; +} + +bool WebView::unsetBasicSetting(Evas_Object* webview) +{ + LogD("enter"); + + if (!webview) { + return false; + } + + for (auto it = m_smartCallbacksMap.begin(); + it != m_smartCallbacksMap.end(); it++) { + evas_object_smart_callback_del( + m_topWebview, it->first.c_str(), it->second); + } + + return true; +} + +std::string WebView::validateUrl(std::string& url) +{ + LogD("enter"); + + if (url.empty()) { + return std::string(); + } + + if((!url.compare(0, 4, "http")) || + (!url.compare(0, 5, "https")) || + (!url.compare(0, 4, "file"))) + { + return url; + } + + std::string newUrl("file://"); + newUrl += url; + return newUrl; +} + +void WebView::loadStartedCallback( + void* data, Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(eventInfo); + + WebView* This = static_cast<WebView*>(data); + + std::ifstream jsFile(injectionFile); + std::string script((std::istreambuf_iterator<char>(jsFile)), + std::istreambuf_iterator<char>()); + LogD("injected js code: %s", script.c_str()); + + ewk_view_script_execute(obj, script.c_str(), executeScriptCallback, This); + This->didLoadStarted(obj); +} + +void WebView::loadFinishedCallback( + void* data, Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(eventInfo); + + WebView* This = static_cast<WebView*>(data); + This->didLoadFinished(obj); +} + +void WebView::titleChangedCallback( + void* data, Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(eventInfo); + + WebView* This = static_cast<WebView*>(data); + This->didTitleChanged(obj, eventInfo); +} + +void WebView::uriChangedCallback( + void* data, Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(eventInfo); + + WebView* This = static_cast<WebView*>(data); + This->didUriChanged(obj, eventInfo); +} + +void WebView::loadProgressCallback( + void* data, Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(eventInfo); + + WebView* This = static_cast<WebView*>(data); + This->didLoadProgress(obj, eventInfo); +} + +void WebView::loadProgressFinishedCallback( + void* data, Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(eventInfo); + + WebView* This = static_cast<WebView*>(data); + This->didLoadProgressFinished(obj); +} + +void WebView::processCrashedCallback( + void* data, Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(eventInfo); + + WebView* This = static_cast<WebView*>(data); + This->didProcessCrashed(obj); +} + +void WebView::createWindowCallback( + void* data, Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(eventInfo); + + WebView* This = static_cast<WebView*>(data); + This->didCreateWindow(obj, eventInfo); +} + +void WebView::closeWindowCallback( + void* data, Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(eventInfo); + + WebView* This = static_cast<WebView*>(data); + This->didCloseWindow(obj); +} + +void WebView::policyNavigationDecideCallback( + void* data, Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + + WebView* This = static_cast<WebView*>(data); + This->didPolicyNavigationDecide(obj, eventInfo); +} + +void WebView::policyNewWindowDecideCallback( + void* data, Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + + WebView* This = static_cast<WebView*>(data); + This->didPolicyNewWindowDecide(obj, eventInfo); +} + +void WebView::pageResponseDecideCallback( + void* data, Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + + Ewk_Policy_Decision *policyDecision = static_cast<Ewk_Policy_Decision *>(eventInfo); + Ewk_Policy_Decision_Type policyType = ewk_policy_decision_type_get(policyDecision); + std::string url(ewk_policy_decision_url_get(policyDecision)); + std::string cookie(ewk_policy_decision_cookie_get(policyDecision)); + const char* contentType = ewk_policy_decision_response_mime_get(policyDecision); + + switch (policyType) { + case EWK_POLICY_DECISION_USE: + LogD("policy use"); + ewk_policy_decision_use(policyDecision); + break; + + case EWK_POLICY_DECISION_DOWNLOAD: + LogD("policy download: %s, %s, %s", url.c_str(), cookie.c_str(), contentType); + ewk_policy_decision_suspend(policyDecision); + Service::AppControl::launchDownloader(url, cookie); + ewk_policy_decision_ignore(policyDecision); + break; + + case EWK_POLICY_DECISION_IGNORE: + default: + LogD("policy ignore"); + ewk_policy_decision_ignore(policyDecision); + break; + } + + if (policyType == EWK_POLICY_DECISION_DOWNLOAD) { + if (ewk_view_back_possible(obj)) { + ewk_view_back(obj); + } else { + // TODO Add handling code in case that new window is opened + //ecore_idler_add(windowCloseIdlerCallback, data); + } + } + + WebView* This = static_cast<WebView*>(data); + This->didPageResponseDecide(obj); +} + +void WebView::contextmenuCustomizeCallback( + void* data, Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + + WebView* This = static_cast<WebView*>(data); + This->didContextmenuCustomize(obj, eventInfo); +} + +void WebView::formSubmitCallback( + void* data, Evas_Object *obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(eventInfo); + + WebView* This = static_cast<WebView*>(data); + This->didFormSubmit(obj); +} + +void WebView::geolocationPermissionRequestCallback( + void* data, Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + + WebView* This = static_cast<WebView*>(data); + This->didGeolocationPermissionRequest(obj, eventInfo); +} + +void WebView::notificationShowCallback( + void* data, Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + + WebView* This = static_cast<WebView*>(data); + This->didNotificationShow(obj, eventInfo); +} + +void WebView::notificationCancelCallback( + void* data, Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + + WebView* This = static_cast<WebView*>(data); + This->didNotificationCancel(obj, eventInfo); +} + +void WebView::notificationPermissionRequestCallback( + void* data, Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + + WebView* This = static_cast<WebView*>(data); + This->didNotificationPermissionRequest(obj, eventInfo); +} + +void WebView::databaseUsagePermissionRequestCallback( + void* data, Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + + WebView* This = static_cast<WebView*>(data); + This->didDatabaseUsagePermissionRequest(obj, eventInfo); +} + +void WebView::fileSystemPermissionRequestCallback( + void* data, Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + + WebView* This = static_cast<WebView*>(data); + This->didFilesystemPermissionRequest(obj, eventInfo); +} + +void WebView::enterFullscreenCallback( + void* data, Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(eventInfo); + + WebView* This = static_cast<WebView*>(data); + This->didEnterFullscreen(obj); +} + +void WebView::exitFullscreenCallback( + void* data, Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(eventInfo); + + WebView* This = static_cast<WebView*>(data); + This->didExitFullscreen(obj); +} + +void WebView::imeChangedCallback( + void* data, Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + + WebView* This = static_cast<WebView*>(data); + This->didImeChanged(obj, eventInfo); +} + +void WebView::imeOpenedCallback( + void* data, Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(eventInfo); + + WebView* This = static_cast<WebView*>(data); + This->didImeOpened(obj); +} + +void WebView::imeClosedCallback( + void* data, Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(eventInfo); + + WebView* This = static_cast<WebView*>(data); + This->didImeClosed(obj); +} + +void WebView::usermediaPermissionRequestCallback( + void* data, Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + + WebView* This = static_cast<WebView*>(data); + This->didUsermediaPermissionRequest(obj, eventInfo); +} + +void WebView::protocolHandlerRegistrationCallback( + void* data, Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + + WebView* This = static_cast<WebView*>(data); + This->didProtocolHandlerRegistration(obj, eventInfo); +} + +void WebView::protocolHandlerIsRegisteredCallback( + void* data, Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + + WebView* This = static_cast<WebView*>(data); + This->didProtocolHandlerIsRegistered(obj, eventInfo); +} + +void WebView::protocolHandlerUnregistrationCallback( + void* data, Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + + WebView* This = static_cast<WebView*>(data); + This->didProtocolHandlerUnregistration(obj, eventInfo); +} + +void WebView::contentHandlerRegistrationCallback( + void* data, Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + + WebView* This = static_cast<WebView*>(data); + This->didContentHandlerRegistration(obj, eventInfo); +} + +void WebView::contentHandlerIsRegisteredCallback( + void* data, Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + + WebView* This = static_cast<WebView*>(data); + This->didContentHandlerIsRegistered(obj, eventInfo); +} + +void WebView::contentHandlerUnregistrationCallback( + void* data, Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + + WebView* This = static_cast<WebView*>(data); + This->didContentHandlerUnregistration(obj, eventInfo); +} + +void WebView::certificateConfirmRequestCallback( + void* data, Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + + WebView* This = static_cast<WebView*>(data); + This->didCertificateConfirmRequest(obj, eventInfo); +} + +void WebView::didLoadStarted(Evas_Object* obj) +{ + LogD("enter"); + UNUSED_PARAM(obj); + + // This Will be implemented by derived class +} + +void WebView::didLoadFinished(Evas_Object* obj) +{ + LogD("enter"); + UNUSED_PARAM(obj); + // This Will be implemented by derived class +} + +void WebView::didTitleChanged(Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(obj); + UNUSED_PARAM(eventInfo); + + // This Will be implemented by derived class +} + +void WebView::didUriChanged(Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(obj); + UNUSED_PARAM(eventInfo); + // This Will be implemented by derived class +} + +void WebView::didLoadProgress(Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(obj); + UNUSED_PARAM(eventInfo); + // This Will be implemented by derived class +} + +void WebView::didLoadProgressFinished(Evas_Object* obj) +{ + LogD("enter"); + UNUSED_PARAM(obj); + // This Will be implemented by derived class +} + +void WebView::didProcessCrashed(Evas_Object* obj) +{ + LogD("enter"); + UNUSED_PARAM(obj); + // This Will be implemented by derived class +} + +void WebView::didCreateWindow(Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(obj); + UNUSED_PARAM(eventInfo); + // This Will be implemented by derived class +} + +void WebView::didCloseWindow(Evas_Object* obj) +{ + LogD("enter"); + UNUSED_PARAM(obj); + // This Will be implemented by derived class +} + +void WebView::didPolicyNavigationDecide(Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(obj); + UNUSED_PARAM(eventInfo); + // This Will be implemented by derived class +} + +void WebView::didPolicyNewWindowDecide(Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(obj); + UNUSED_PARAM(eventInfo); + // This Will be implemented by derived class +} + +void WebView::didPageResponseDecide(Evas_Object* obj) +{ + LogD("enter"); + UNUSED_PARAM(obj); + // This Will be implemented by derived class +} + +void WebView::didContextmenuCustomize(Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(obj); + UNUSED_PARAM(eventInfo); + // This Will be implemented by derived class +} + +void WebView::didFormSubmit(Evas_Object* obj) +{ + LogD("enter"); + UNUSED_PARAM(obj); + // This Will be implemented by derived class +} + +void WebView::didGeolocationPermissionRequest(Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(obj); + UNUSED_PARAM(eventInfo); + // This Will be implemented by derived class +} + +void WebView::didNotificationShow(Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(obj); + UNUSED_PARAM(eventInfo); + // This Will be implemented by derived class +} + +void WebView::didNotificationCancel(Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(obj); + UNUSED_PARAM(eventInfo); + // This Will be implemented by derived class +} + +void WebView::didNotificationPermissionRequest(Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(obj); + UNUSED_PARAM(eventInfo); + // This Will be implemented by derived class +} + +void WebView::didDatabaseUsagePermissionRequest(Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(obj); + UNUSED_PARAM(eventInfo); + // This Will be implemented by derived class +} + +void WebView::didFilesystemPermissionRequest(Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(obj); + UNUSED_PARAM(eventInfo); + // This Will be implemented by derived class +} + +void WebView::didEnterFullscreen(Evas_Object* obj) +{ + LogD("enter"); + UNUSED_PARAM(obj); + // This Will be implemented by derived class +} + +void WebView::didExitFullscreen(Evas_Object* obj) +{ + LogD("enter"); + UNUSED_PARAM(obj); + // This Will be implemented by derived class +} + +void WebView::didImeChanged(Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(obj); + UNUSED_PARAM(eventInfo); + // This Will be implemented by derived class +} + +void WebView::didImeOpened(Evas_Object* obj) +{ + LogD("enter"); + UNUSED_PARAM(obj); + // This Will be implemented by derived class +} + +void WebView::didImeClosed(Evas_Object* obj) +{ + LogD("enter"); + UNUSED_PARAM(obj); + // This Will be implemented by derived class +} + +void WebView::didUsermediaPermissionRequest(Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(obj); + UNUSED_PARAM(eventInfo); + // This Will be implemented by derived class +} + +void WebView::didProtocolHandlerRegistration(Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(obj); + UNUSED_PARAM(eventInfo); + // This Will be implemented by derived class +} + +void WebView::didProtocolHandlerIsRegistered(Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(obj); + UNUSED_PARAM(eventInfo); + // This Will be implemented by derived class +} + +void WebView::didProtocolHandlerUnregistration(Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(obj); + UNUSED_PARAM(eventInfo); + // This Will be implemented by derived class +} + +void WebView::didContentHandlerRegistration(Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(obj); + UNUSED_PARAM(eventInfo); + // This Will be implemented by derived class +} + +void WebView::didContentHandlerIsRegistered(Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(obj); + UNUSED_PARAM(eventInfo); + // This Will be implemented by derived class +} + +void WebView::didContentHandlerUnregistration(Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(obj); + UNUSED_PARAM(eventInfo); + // This Will be implemented by derived class +} + +void WebView::didCertificateConfirmRequest(Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(obj); + UNUSED_PARAM(eventInfo); + // This Will be implemented by derived class +} + +Eina_Bool WebView::orientationLockCallback( + Evas_Object* obj, Eina_Bool needLock, int orientation, void* data) +{ + LogD("enter"); + UNUSED_PARAM(obj); + UNUSED_PARAM(needLock); + UNUSED_PARAM(orientation); + UNUSED_PARAM(data); + return EINA_TRUE; +} + +void WebView::executeScriptCallback( + Evas_Object* obj, const char* result, void* data) +{ + LogD("enter"); + UNUSED_PARAM(obj); + UNUSED_PARAM(result); + UNUSED_PARAM(data); +} + +void WebView::consoleMessageCallback(void* data, Evas_Object* obj, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(obj); + + WebView* This = static_cast<WebView*>(data); + + Ewk_Console_Message* consoleMessage = + static_cast<Ewk_Console_Message*>(eventInfo); + + std::stringstream buf; + unsigned int lineNumber = ewk_console_message_line_get(consoleMessage); + const char* source = ewk_console_message_source_get(consoleMessage); + const char* text = ewk_console_message_text_get(consoleMessage); + if (lineNumber) { + buf << source << ":" << lineNumber << ":"; + } + buf << text; + This->consoleMessage(ewk_console_message_level_get(consoleMessage), buf.str().c_str()); +} + +void WebView::consoleMessage(int level, const char* message) +{ + LogD("enter"); + + // this console message should be secure mode + switch (level) { + case EWK_CONSOLE_MESSAGE_LEVEL_DEBUG: + SECURE_LOG(LOG_DEBUG, consoleMessageDlogTag, "%s", message); + break; + case EWK_CONSOLE_MESSAGE_LEVEL_WARNING: + SECURE_LOG(LOG_WARN, consoleMessageDlogTag, "%s", message); + break; + case EWK_CONSOLE_MESSAGE_LEVEL_ERROR: + SECURE_LOG(LOG_ERROR, consoleMessageDlogTag, "%s", message); + break; + default: + SECURE_LOG(LOG_DEBUG, consoleMessageDlogTag, "%s", message); + break; + } +} diff --git a/src_wearable/Core/View/WebView.h b/src_wearable/Core/View/WebView.h new file mode 100644 index 0000000..4c9dee1 --- /dev/null +++ b/src_wearable/Core/View/WebView.h @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file WebView.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef WEB_VIEW_H +#define WEB_VIEW_H + +#include <string> +#include <map> +#include <Eina.h> +#include <Evas.h> +#include <ewk_context.h> +#include "IWebView.h" + +#define EXPORT_CLASS __attribute__ ((visibility("default"))) + +class EXPORT_CLASS WebView: public IWebView { + public: + static IWebViewPtr create(Evas_Object* win, Ewk_Context* ewkContext) + { + if (!win || !ewkContext) { + return IWebViewPtr(); + } + + return IWebViewPtr(new WebView(win, ewkContext)); + } + virtual bool show( + std::string& startUrl, int width, int height, + WebViewCallback didCreateBaseWebView, void* data); + virtual bool hide(); + virtual bool suspend(); + virtual bool resume(); + virtual ~WebView(); + + protected: + bool setBasicSetting(Evas_Object* webview); + bool unsetBasicSetting(Evas_Object* webview); + explicit WebView(Evas_Object* win, Ewk_Context* ewkContext); + + private: + std::string validateUrl(std::string& url); + void consoleMessage(int level, const char* message); + + // webviw smart callbacks + static void loadStartedCallback( + void* data, Evas_Object* obj, void* eventInfo); + static void loadFinishedCallback( + void* data, Evas_Object* obj, void* eventInfo); + static void titleChangedCallback( + void* data, Evas_Object* obj, void* eventInfo); + static void uriChangedCallback( + void* data, Evas_Object* obj, void* eventInfo); + static void loadProgressCallback( + void* data, Evas_Object* obj, void* eventInfo); + static void loadProgressFinishedCallback( + void* data, Evas_Object* obj, void* eventInfo); + static void processCrashedCallback( + void* data, Evas_Object* obj, void* eventInfo); + static void createWindowCallback( + void* data, Evas_Object* obj, void* eventInfo); + static void closeWindowCallback( + void* data, Evas_Object* obj, void* eventInfo); + static void policyNavigationDecideCallback( + void* data, Evas_Object* obj, void* eventInfo); + static void policyNewWindowDecideCallback( + void* data, Evas_Object* obj, void* eventInfo); + static void pageResponseDecideCallback( + void* data, Evas_Object* obj, void* eventInfo); + static void contextmenuCustomizeCallback( + void* data, Evas_Object* obj, void* eventInfo); + static void formSubmitCallback( + void *data, Evas_Object *obj, void *eventInfo); + static void geolocationPermissionRequestCallback( + void* data, Evas_Object* obj, void* eventInfo); + static void notificationShowCallback( + void* data, Evas_Object* obj, void* eventInfo); + static void notificationCancelCallback( + void* data, Evas_Object* obj, void* eventInfo); + static void notificationPermissionRequestCallback( + void* data, Evas_Object* obj, void* eventInfo); + static void databaseUsagePermissionRequestCallback( + void* data, Evas_Object* obj, void* eventInfo); + static void fileSystemPermissionRequestCallback( + void* data, Evas_Object* obj, void* eventInfo); + static void enterFullscreenCallback( + void* data, Evas_Object* obj, void* eventInfo); + static void exitFullscreenCallback( + void* data, Evas_Object* obj, void* eventInfo); + static void imeChangedCallback( + void* data, Evas_Object* obj, void* eventInfo); + static void imeOpenedCallback( + void* data, Evas_Object* obj, void* eventInfo); + static void imeClosedCallback( + void* data, Evas_Object* obj, void* eventInfo); + static void usermediaPermissionRequestCallback( + void* data, Evas_Object* obj, void* eventInfo); + static void protocolHandlerRegistrationCallback( + void* data, Evas_Object* obj, void* eventInfo); + static void protocolHandlerIsRegisteredCallback( + void* data, Evas_Object* obj, void* eventInfo); + static void protocolHandlerUnregistrationCallback( + void* data, Evas_Object* obj, void* eventInfo); + static void contentHandlerRegistrationCallback( + void* data, Evas_Object* obj, void* eventInfo); + static void contentHandlerIsRegisteredCallback( + void* data, Evas_Object* obj, void* eventInfo); + static void contentHandlerUnregistrationCallback( + void* data, Evas_Object* obj, void* eventInfo); + static void certificateConfirmRequestCallback( + void* data, Evas_Object* obj, void* eventInfo); + static void consoleMessageCallback(void* data, Evas_Object* obj, void* eventInfo); + + // internal implementation for smart callbacks + virtual void didLoadStarted(Evas_Object* obj); + virtual void didLoadFinished(Evas_Object* obj); + virtual void didTitleChanged(Evas_Object* obj, void* eventInfo); + virtual void didUriChanged(Evas_Object* obj, void* eventInfo); + virtual void didLoadProgress(Evas_Object* obj, void* eventInfo); + virtual void didLoadProgressFinished(Evas_Object* obj); + virtual void didProcessCrashed(Evas_Object* obj); + virtual void didCreateWindow(Evas_Object* obj, void* eventInfo); + virtual void didCloseWindow(Evas_Object* obj); + virtual void didPolicyNavigationDecide(Evas_Object* obj, void* eventInfo); + virtual void didPolicyNewWindowDecide(Evas_Object* obj, void* eventInfo); + virtual void didPageResponseDecide(Evas_Object* obj); + virtual void didContextmenuCustomize(Evas_Object* obj, void* eventInfo); + virtual void didFormSubmit(Evas_Object* obj); + virtual void didGeolocationPermissionRequest(Evas_Object* obj, void* eventInfo); + virtual void didNotificationShow(Evas_Object* obj, void* eventInfo); + virtual void didNotificationCancel(Evas_Object* obj, void* eventInfo); + virtual void didNotificationPermissionRequest(Evas_Object* obj, void* eventInfo); + virtual void didDatabaseUsagePermissionRequest(Evas_Object* obj, void* eventInfo); + virtual void didFilesystemPermissionRequest(Evas_Object* obj, void* eventInfo); + virtual void didEnterFullscreen(Evas_Object* obj); + virtual void didExitFullscreen(Evas_Object* obj); + virtual void didImeChanged(Evas_Object* obj, void* eventInfo); + virtual void didImeOpened(Evas_Object* obj); + virtual void didImeClosed(Evas_Object* obj); + virtual void didUsermediaPermissionRequest(Evas_Object* obj, void* eventInfo); + virtual void didProtocolHandlerRegistration(Evas_Object* obj, void* eventInfo); + virtual void didProtocolHandlerIsRegistered(Evas_Object* obj, void* eventInfo); + virtual void didProtocolHandlerUnregistration(Evas_Object* obj, void* eventInfo); + virtual void didContentHandlerRegistration(Evas_Object* obj, void* eventInfo); + virtual void didContentHandlerIsRegistered(Evas_Object* obj, void* eventInfo); + virtual void didContentHandlerUnregistration(Evas_Object* obj, void* eventInfo); + virtual void didCertificateConfirmRequest(Evas_Object* obj, void* eventInfo); + + // orientation lock + static Eina_Bool orientationLockCallback( + Evas_Object* obj, Eina_Bool needLock, int orientation, void* data); + static void executeScriptCallback(Evas_Object* obj, const char* result, void* data); + + static std::map<const std::string, const Evas_Smart_Cb> m_smartCallbacksMap; + + // members + Evas_Object* m_topWebview; + std::string m_startUrl; + Evas_Object* m_win; + Ewk_Context* m_ewkContext; +}; + +#endif // WEB_VIEW_H diff --git a/src_wearable/Core/View/injection.js b/src_wearable/Core/View/injection.js new file mode 100644 index 0000000..32ba93c --- /dev/null +++ b/src_wearable/Core/View/injection.js @@ -0,0 +1,151 @@ +// set javascript objects for Web APIs of Tizen appwidget +var appTizenObject = 0; +if (typeof window.tizen == 'undefined') { + window.tizen = new Object(); + window.tizen.appwidget = new Object(); +} else { + appTizenObject = 1; +} + +// For future, only window.appwidget will be used +window.appwidget = new Object(); + + +window.appwidget.fireReadyEvent = function () { + // If every functionalities of appwidget are initialized, fire appwidget ready event + var readyevent = document.createEvent("CustomEvent"); + readyevent.initCustomEvent("appwidgetready", true, true); + document.dispatchEvent(readyevent); +}; + +// these are functions for overriding standard javascript functions regarding event +var original_addEventListener = window.addEventListener; +var original_removeEventListener = window.removeEventListener; + +// this variable is responsible to keep information of appwidget evetns +var appWidgetEvents = {}; + +// define event structure for appwidget +window.AppWidgetEventInfo = function(event, callback) { + this.event = event; + this.callback = callback; +}; + +// this variable is responsible to keep information of box +var appWidgetContexts = {}; + +// define box info for appwidget (e.g. box id, box instance id) +window.AppWidgetContextInfo = function(key, value) { + this.key = key; + this.value = value; +}; + +window.addEventListener = function(event, callback, capture) { + var e = event.toLowerCase(); + if (typeof appWidgetEvents[e] != 'undefined') { + appWidgetEvents[e].callback = callback; + } else { + original_addEventListener.call(window, event, callback, capture); + } + + if (e == 'appwidgetready') { + // fire ready event to content + setTimeout(window.appwidget.fireReadyEvent(), 0); + } +}; + +window.removeEventListener = function(event, callback, capture) { + var e = event.toLowerCase(); + if (typeof appWidgetEvents[e] != "undefined") { + appWidgetEvents[e].callback = "null"; + } else { + original_removeEventListener.call(window, event, callback, capture); + } +}; + +window.appwidget.reload = function() { + window.location.href = "box://reload"; +}; + +window.appwidget.changePeriod = function(period) { + switch (arguments.length) { + case 0: + window.location.href = "box://change-period"; + break; + case 1: + window.location.href = "box://change-period?period=" + period; + break; + default: + window.location.href = "box://change-period"; + break; + } +}; + +window.appwidget.launchBrowser = function(url) { + window.location.href = "box://launch-browser?url=" + url; +}; + +window.appwidget.scrollStart = function() { + window.location.href = "box://scroll-start"; +}; + +window.appwidget.scrollStop = function() { + window.location.href = "box://scroll-stop"; +}; + +window.appwidget.sendMessageToBox = function(message) { + window.location.href = "box://send-message-to-box?message=" + message; +}; + +window.appwidget.sendMessageToPd = function(message) { + window.location.href = "box://send-message-to-pd?message=" + message; +}; + +window.appwidget.getBoxId = function() { + return appWidgetContexts["box-id"].value; +}; + +window.appwidget.getBoxInstanceId = function() { + return appWidgetContexts["instance-id"].value; +}; + +var webprovider = { + // define specific function for registering appwidget event + registerAppWidgetEvent: function(event) { + return (appWidgetEvents[event] = new AppWidgetEventInfo(event, "null")); + }, + + // register resources for synchronous APIs like getBoxId, getBoxInstanceId + registerAppWidgetContextInfo: function(key, value) { + return (appWidgetContexts[key] = new AppWidgetContextInfo(key, value)); + }, + + // define specific function for firing registered appwidget event + fireAppWidgetEvent: function(event, data) { + // this is called by web-provider, which is native code + if (typeof appWidgetEvents[event] != 'undefined') { + setTimeout(function() { + appWidgetEvents[event].callback(data); + }, 0); + console.log("fire appwidget event: " + event); + } else { + console.log("unknown appwidget event: " + event); + } + }, +}; + +// register custom events for appwidget +webprovider.registerAppWidgetEvent("pdmessage"); +webprovider.registerAppWidgetEvent("boxmessage"); + +// These objects will be deprecated soon +if (!appTizenObject) { + window.tizen.appwidget.reload = window.appwidget.reload; + window.tizen.appwidget.changePeriod = window.appwidget.changePeriod; + window.tizen.appwidget.launchBrowser = window.appwidget.launchBrowser; + window.tizen.appwidget.scrollStart = window.appwidget.scrollStart; + window.tizen.appwidget.scrollStop = window.appwidget.scrollStop; +} + +// fire ready event explicitly +window.appwidget.fireReadyEvent(); diff --git a/src_wearable/Core/config.h b/src_wearable/Core/config.h new file mode 100644 index 0000000..52d0d61 --- /dev/null +++ b/src_wearable/Core/config.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file config.h + * @author Minhyung Ko (minhyung.ko@samsung.com) + */ + +#include <Core/Platform.h> + +/*** define list **/ +#define WEB_PROVIDER_INSPECTOR_PORT_NUMBER 9980 +#define WEB_PROVIDER_INSPECTOR_FILE_PATH "/tmp/inspector" diff --git a/src_wearable/Daemon/BoxDaemon.cpp b/src_wearable/Daemon/BoxDaemon.cpp new file mode 100644 index 0000000..d58153b --- /dev/null +++ b/src_wearable/Daemon/BoxDaemon.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file BoxDaemon.cpp + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#include <string> +#include <app.h> +#include "BoxDaemon.h" +#include "BoxDaemonImpl.h" + +BoxDaemon::BoxDaemon() + : m_impl(new BoxDaemonImpl()) +{ +} + +BoxDaemon::~BoxDaemon() +{ +} + +bool BoxDaemon::start(std::string& name) +{ + return m_impl->start(name); +} + +bool BoxDaemon::stop() +{ + return m_impl->stop(); +} + +bool BoxDaemon::handleAppService(service_h service) +{ + return m_impl->handleAppService(service); +} diff --git a/src_wearable/Daemon/BoxDaemon.h b/src_wearable/Daemon/BoxDaemon.h new file mode 100644 index 0000000..f1bde75 --- /dev/null +++ b/src_wearable/Daemon/BoxDaemon.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file BoxDaemon.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef BOX_DAEMON_H +#define BOX_DAEMON_H + +#include <string> +#include <memory> +#include <app.h> +#include <Core/Util/Noncopyable.h> + +class BoxDaemonImpl; + +class BoxDaemon: Noncopyable { + public: + bool start(std::string& name); + bool stop(); + bool handleAppService(service_h service); + + explicit BoxDaemon(); + ~BoxDaemon(); + + private: + std::shared_ptr<BoxDaemonImpl> m_impl; +}; + +#endif //BOX_DAEMON_H diff --git a/src_wearable/Daemon/BoxDaemonImpl.cpp b/src_wearable/Daemon/BoxDaemonImpl.cpp new file mode 100755 index 0000000..5cf22eb --- /dev/null +++ b/src_wearable/Daemon/BoxDaemonImpl.cpp @@ -0,0 +1,790 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file BoxDaemonImpl.cpp + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#include <cstring> +#include <sys/types.h> +#include <string> +#include <unistd.h> +#include <vector> + +#include <app.h> +#include <appcore-efl.h> +#include <aul.h> +#include <Ecore_X.h> +#include <Elementary.h> +#include <livebox-service.h> +#include <provider.h> +#include <vconf.h> + +#include <API/web_provider_livebox_info.h> +#include <API/web_provider_service.h> +#include <Core/Util/Log.h> +#include <Core/Util/Util.h> +#include <Plugin/IBoxPluginConnector.h> +#include <Plugin/BoxPluginConnector.h> + +#include "BoxDaemonUtil.h" +#include "BoxDaemonImpl.h" + +#define MASTER_PROVIDER_PING_TIME 120.0f + +BoxDaemonImpl::BoxDaemonImpl() + : m_pluginConnector(BoxPluginConnector::create()) +{ + appcore_set_event_callback(APPCORE_EVENT_LANG_CHANGE, requestUpdateAllCallback, this); + appcore_set_event_callback(APPCORE_EVENT_LOW_MEMORY, requestLowMemoryCallback, this); + appcore_set_event_callback(APPCORE_EVENT_REGION_CHANGE, requestUpdateAllCallback, this); + // reserved + appcore_set_event_callback(APPCORE_EVENT_LOW_BATTERY, NULL, NULL); + + if (vconf_notify_key_changed("db/setting/accessibility/font_name", requestUpdateAllCallback, this) != 0) { + LogD("vconf_notify_key_changed returned FALSE!"); + } + if (vconf_notify_key_changed(VCONFKEY_SYSTEM_TIME_CHANGED, requestUpdateAppBoxCallback, this) != 0) { + LogD("vconf_notify_key_changed returned FALSE!"); + } + if (vconf_notify_key_changed(VCONFKEY_NETWORK_WIFI_STATE, requestUpdateAppBoxCallback, this) != 0) { + LogD("vconf_notify_key_changed returned FALSE!"); + } + if (vconf_notify_key_changed(VCONFKEY_NETWORK_CELLULAR_STATE, requestUpdateAppBoxCallback, this) != 0) { + LogD("vconf_notify_key_changed returned FALSE!"); + } +} + +BoxDaemonImpl::~BoxDaemonImpl() +{ +} + +bool BoxDaemonImpl::start(std::string& name) +{ + LogD("enter"); + + // initialize existing plugins for web livebox + if (!m_pluginConnector->initialize()) { + LogD("failed to initialize plugins"); + return false; + } + + // set name + m_daemonName = name; + + // provider init + ProviderCallbacks callbacks; + setProviderCallbacks(callbacks); + + int ret = provider_init_with_options(ecore_x_display_get(), + m_daemonName.c_str(), + &callbacks, + this, 1, 1); + if (ret < 0) { + LogD("failed to initialize provider"); + return false; + } + + return true; +} + +bool BoxDaemonImpl::stop() +{ + LogD("enter"); + + // deinitialize provider + provider_fini(); + + // deinitialize existing plugins for web livebox + if (!m_pluginConnector->shutdown()) { + LogD("failed to shutdown plugins"); + return false; + } + + return true; +} + +bool BoxDaemonImpl::handleAppService(service_h service) +{ + LogD("enter"); + bool result = false; + char* operation; + + if (service_get_operation(service, &operation) != SERVICE_ERROR_NONE) { + LogD("no operation"); + return false; + } + + if (!strcmp(SERVICE_OPERATION_BOX_UPDATE, operation)) { + BoxInfoPtr info = handleOperationUpdate(service); + if (info) { + JobInfo* jobInfo = new JobInfo(REQUEST_CMD_UPDATE_BOX, info, this); + if (ecore_job_add(requestBoxJobCallback, jobInfo)) { + result = true; + } + } + } else if (!strcmp(SERVICE_OPERATION_BOX_REMOVE, operation)) { + std::vector<BoxInfoPtr> container = handleOperationRemove(service); + for (unsigned i = 0; i < container.size(); i++) { + // directly remove box not using ecore job, + // because removing box is timing-senstive job + m_pluginConnector->requestCommand(REQUEST_CMD_REMOVE_BOX, container[i]); + } + + // wake up pended process like installer + char* appId; + service_get_extra_data(service, SERVICE_REMOVE_APPID_KEY, &appId); + web_provider_service_wakeup_installer(appId); + result = true; + } else { + LogD("unknown operation: %s", operation); + } + + delete[] operation; + return result; +} + +int BoxDaemonImpl::connectedCallback(ProviderEventArgPtr arg, void* data) +{ + LogD("enter"); + UNUSED_PARAM(arg); + + BoxDaemonImpl* This = static_cast<BoxDaemonImpl*>(data); + if (!provider_send_hello()) { + This->m_pingTimer = + ecore_timer_add(MASTER_PROVIDER_PING_TIME, pingToMasterCallback, This); + } + + return 0; +} + +int BoxDaemonImpl::disconnectedCallback(ProviderEventArgPtr arg, void* data) +{ + LogD("enter"); + UNUSED_PARAM(arg); + UNUSED_PARAM(data); + + return 0; +} + +int BoxDaemonImpl::boxCreateCallback( + ProviderEventArgPtr arg, + int* width, int* height, + double* priority, void* data) +{ + LogD("enter"); + UNUSED_PARAM(priority); + + BoxDaemonImpl* This = static_cast<BoxDaemonImpl*>(data); + BoxInfoPtr info = This->initializeBoxInfo(arg); + if (!info) { + return -1; + } + + if ((arg->info.lb_create.width == 0) || (arg->info.lb_create.height == 0)) { + livebox_service_get_size(LB_SIZE_TYPE_1x1, width, height); + } else { + *width = arg->info.lb_create.width; + *height = arg->info.lb_create.height; + } + + info->boxWidth = *width; + info->boxHeight = *height; + info->priority = 1.0f; + info->period = arg->info.lb_create.period; + if (arg->info.lb_create.content && strlen(arg->info.lb_create.content)) { + info->contentInfo = std::string(arg->info.lb_create.content); + } else { + // we generate our instance id + info->contentInfo = BoxDaemonUtil::createWebInstanceId(info->boxId); + } + + // box information + LogD("--------------------------------------------"); + LogD("boxId: %s", info->boxId.c_str()); + LogD("InstanceId: %s", info->instanceId.c_str()); + LogD("width: %d", info->boxWidth); + LogD("height: %d", info->boxHeight); + LogD("update period: %f", info->period); + LogD("content info: %s", info->contentInfo.c_str()); + LogD("--------------------------------------------"); + + bool ret = This->m_pluginConnector->requestCommand(REQUEST_CMD_ADD_BOX, info); + return ret ? 0 : -1; +} + +int BoxDaemonImpl::boxReCreateCallback(ProviderEventArgPtr arg, void* data) +{ + LogD("enter"); + + BoxDaemonImpl* This = static_cast<BoxDaemonImpl*>(data); + BoxInfoPtr info = This->initializeBoxInfo(arg); + if (!info) { + return -1; + } + + if ((arg->info.lb_recreate.width == 0) || (arg->info.lb_recreate.height == 0)) { + livebox_service_get_size(LB_SIZE_TYPE_1x1, + &arg->info.lb_recreate.width, + &arg->info.lb_recreate.height); + } + + info->boxWidth = arg->info.lb_recreate.width; + info->boxHeight = arg->info.lb_recreate.height; + info->priority = 1.0f; + info->period = arg->info.lb_recreate.period; + if (arg->info.lb_recreate.content) { + info->contentInfo = std::string(arg->info.lb_recreate.content); + } + + // box information + LogD("--------------------------------------------"); + LogD("boxId: %s", info->boxId.c_str()); + LogD("InstanceId: %s", info->instanceId.c_str()); + LogD("width: %d", info->boxWidth); + LogD("height: %d", info->boxHeight); + LogD("update period: %f", info->period); + LogD("content info: %s", info->contentInfo.c_str()); + LogD("--------------------------------------------"); + + bool ret = This->m_pluginConnector->requestCommand(REQUEST_CMD_ADD_BOX, info); + return ret ? 0 : -1; +} + +int BoxDaemonImpl::boxDestroyCallback(ProviderEventArgPtr arg, void* data) +{ + LogD("enter"); + + BoxDaemonImpl* This = static_cast<BoxDaemonImpl*>(data); + BoxInfoPtr info = This->initializeBoxInfo(arg); + if (!info) { + return -1; + } + + LogD("--------------------------------------------"); + LogD("boxId: %s", info->boxId.c_str()); + LogD("InstanceId: %s", info->instanceId.c_str()); + LogD("--------------------------------------------"); + + This->m_pluginConnector->requestCommand(REQUEST_CMD_REMOVE_BOX, info); + + return 0; +} + +int BoxDaemonImpl::pdCreateCallback(ProviderEventArgPtr arg, void* data) +{ + LogD("enter"); + + BoxDaemonImpl* This = static_cast<BoxDaemonImpl*>(data); + BoxInfoPtr info = This->initializeBoxInfo(arg); + if (!info) { + return -1; + } + if (arg->info.pd_create.w == 0 || arg->info.pd_create.h == 0) { + return -1; + } + + //Use the screen width to fix the device width + ecore_x_window_size_get(0, &info->pdWidth, NULL); + info->pdHeight = arg->info.pd_create.h; + info->pdX = arg->info.pd_create.x; + info->pdY = arg->info.pd_create.y; + + LogD("--------------------------------------------"); + LogD("boxId: %s", info->boxId.c_str()); + LogD("InstanceId: %s", info->instanceId.c_str()); + LogD("width: %d", info->pdWidth); + LogD("height: %d", info->pdHeight); + LogD("x: %f", info->pdX); + LogD("y: %f", info->pdY); + LogD("--------------------------------------------"); + + JobInfo* jobInfo = new JobInfo(REQUEST_CMD_OPEN_PD, info, This); + Ecore_Job* ret = ecore_job_add(requestBoxJobCallback, jobInfo); + + return ret ? 0 : -1; +} + +int BoxDaemonImpl::pdDestroyCallback(ProviderEventArgPtr arg, void* data) +{ + LogD("enter"); + + BoxDaemonImpl* This = static_cast<BoxDaemonImpl*>(data); + BoxInfoPtr info = This->initializeBoxInfo(arg); + if (!info) { + return -1; + } + + LogD("--------------------------------------------"); + LogD("boxId: %s", info->boxId.c_str()); + LogD("InstanceId: %s", info->instanceId.c_str()); + LogD("--------------------------------------------"); + + JobInfo* jobInfo = new JobInfo(REQUEST_CMD_CLOSE_PD, info, This); + Ecore_Job* ret = ecore_job_add(requestBoxJobCallback, jobInfo); + + return ret ? 0 : -1; +} + +int BoxDaemonImpl::clickedCallback(ProviderEventArgPtr arg, void* data) +{ + LogD("enter"); + + BoxDaemonImpl* This = static_cast<BoxDaemonImpl*>(data); + BoxInfoPtr info = This->initializeBoxInfo(arg); + if (!info) { + return -1; + } + + int flag = web_provider_livebox_get_auto_launch(info->boxId.c_str()); + if (!flag) { + return -1; + } + + BoxDaemonUtil::launchApplication(info->boxId, info->instanceId); + return 0; +} + +int BoxDaemonImpl::boxResizeCallback(ProviderEventArgPtr arg, void* data) +{ + LogD("enter"); + + BoxDaemonImpl* This = static_cast<BoxDaemonImpl*>(data); + BoxInfoPtr info = This->initializeBoxInfo(arg); + if (!info) { + return -1; + } + if (arg->info.resize.w == 0 || arg->info.resize.h == 0) { + return -1; + } + + info->boxWidth = arg->info.resize.w; + info->boxHeight = arg->info.resize.h; + + // box information + LogD("--------------------------------------------"); + LogD("boxId: %s", info->boxId.c_str()); + LogD("InstanceId: %s", info->instanceId.c_str()); + LogD("width: %d", info->boxWidth); + LogD("height: %d", info->boxHeight); + LogD("--------------------------------------------"); + + JobInfo* jobInfo = new JobInfo(REQUEST_CMD_RESIZE_BOX, info, This); + Ecore_Job* ret = ecore_job_add(requestBoxJobCallback, jobInfo); + + return ret ? 0 : -1; +} + +int BoxDaemonImpl::boxPauseCallback(ProviderEventArgPtr arg, void* data) +{ + LogD("enter"); + + BoxDaemonImpl* This = static_cast<BoxDaemonImpl*>(data); + BoxInfoPtr info = This->initializeBoxInfo(arg); + if (!info) { + return -1; + } + + // box information + LogD("--------------------------------------------"); + LogD("boxId: %s", info->boxId.c_str()); + LogD("InstanceId: %s", info->instanceId.c_str()); + LogD("--------------------------------------------"); + + JobInfo* jobInfo = new JobInfo(REQUEST_CMD_PAUSE_BOX, info, This); + Ecore_Job* ret = ecore_job_add(requestBoxJobCallback, jobInfo); + + return ret ? 0 : -1; +} + +int BoxDaemonImpl::boxResumeCallback(ProviderEventArgPtr arg, void* data) +{ + LogD("enter"); + + BoxDaemonImpl* This = static_cast<BoxDaemonImpl*>(data); + BoxInfoPtr info = This->initializeBoxInfo(arg); + if (!info) { + return -1; + } + + // box information + LogD("--------------------------------------------"); + LogD("boxId: %s", info->boxId.c_str()); + LogD("InstanceId: %s", info->instanceId.c_str()); + LogD("--------------------------------------------"); + + JobInfo* jobInfo = new JobInfo(REQUEST_CMD_RESUME_BOX, info, This); + Ecore_Job* ret = ecore_job_add(requestBoxJobCallback, jobInfo); + + return ret ? 0 : -1; +} + +int BoxDaemonImpl::pauseCallback(ProviderEventArgPtr arg, void* data) +{ + LogD("enter"); + UNUSED_PARAM(arg); + + BoxDaemonImpl* This = static_cast<BoxDaemonImpl*>(data); + + LogD("--------------------------------------------"); + LogD("web-provider is paused"); + LogD("--------------------------------------------"); + + JobInfo* jobInfo = new JobInfo(REQUEST_CMD_PAUSE_ALL, BoxInfoPtr(), This); + Ecore_Job* ret = ecore_job_add(requestBoxJobCallback, jobInfo); + + return ret ? 0 : -1; +} + +int BoxDaemonImpl::resumeCallback(ProviderEventArgPtr arg, void* data) +{ + LogD("enter"); + UNUSED_PARAM(arg); + + BoxDaemonImpl* This = static_cast<BoxDaemonImpl*>(data); + + LogD("--------------------------------------------"); + LogD("web-provider is resumed"); + LogD("--------------------------------------------"); + + JobInfo* jobInfo = new JobInfo(REQUEST_CMD_RESUME_ALL, BoxInfoPtr(), This); + Ecore_Job* ret = ecore_job_add(requestBoxJobCallback, jobInfo); + + return ret ? 0 : -1; +} + +int BoxDaemonImpl::boxPeriodChangeCallback(ProviderEventArgPtr arg, void* data) +{ + LogD("enter"); + BoxDaemonImpl* This = static_cast<BoxDaemonImpl*>(data); + BoxInfoPtr info = This->initializeBoxInfo(arg); + if (!info) { + return -1; + } + info->period = arg->info.set_period.period; + + LogD("--------------------------------------------"); + LogD("boxId: %s", info->boxId.c_str()); + LogD("InstanceId: %s", info->instanceId.c_str()); + LogD("period: %f", info->period); + LogD("--------------------------------------------"); + + JobInfo* jobInfo = new JobInfo(REQUEST_CMD_CHANGE_PERIOD, info, This); + Ecore_Job* ret = ecore_job_add(requestBoxJobCallback, jobInfo); + + return ret ? 0 : -1; +} + +int BoxDaemonImpl::boxUpdateCallback(ProviderEventArgPtr arg, void* data) +{ + LogD("enter"); + + BoxDaemonImpl* This = static_cast<BoxDaemonImpl*>(data); + BoxInfoPtr info = This->initializeBoxInfo(arg); + if (!info) { + return -1; + } + + LogD("--------------------------------------------"); + LogD("boxId: %s", info->boxId.c_str()); + LogD("InstanceId: %s", info->instanceId.c_str()); + LogD("--------------------------------------------"); + + JobInfo* jobInfo = new JobInfo(REQUEST_CMD_UPDATE_BOX, info, This); + Ecore_Job* ret = ecore_job_add(requestBoxJobCallback, jobInfo); + + return ret ? 0 : -1; +} + +void BoxDaemonImpl::setProviderCallbacks(ProviderCallbacks& callbacks) +{ + LogD("enter"); + + memset(&callbacks, 0, sizeof(callbacks)); + callbacks.connected = BoxDaemonImpl::connectedCallback; + callbacks.disconnected = BoxDaemonImpl::disconnectedCallback; + callbacks.pause = BoxDaemonImpl::pauseCallback; + callbacks.resume = BoxDaemonImpl::resumeCallback; + callbacks.lb_create = BoxDaemonImpl::boxCreateCallback; + callbacks.lb_recreate = BoxDaemonImpl::boxReCreateCallback; + callbacks.lb_destroy = BoxDaemonImpl::boxDestroyCallback; + callbacks.lb_pause = BoxDaemonImpl::boxPauseCallback; + callbacks.lb_resume = BoxDaemonImpl::boxResumeCallback; + callbacks.pd_create = BoxDaemonImpl::pdCreateCallback; + callbacks.pd_destroy = BoxDaemonImpl::pdDestroyCallback; + callbacks.clicked = BoxDaemonImpl::clickedCallback; + callbacks.resize = BoxDaemonImpl::boxResizeCallback; + callbacks.update_content = BoxDaemonImpl::boxUpdateCallback; + callbacks.set_period = BoxDaemonImpl::boxPeriodChangeCallback; +} + +std::string BoxDaemonImpl::getBoxType(const char* boxId) +{ + LogD("enter"); + + if (!boxId) { + return std::string(); + } + + const char* type = web_provider_livebox_get_box_type(boxId); + if (!type) { + std::string boxType = m_pluginConnector->getBoxType(boxId); + if (boxType.empty()) { + LogD("unrecognized box id"); + } else { + LogD("box id: %s, type: %s", boxId, boxType.c_str()); + } + return boxType; + } + + LogD("box id: %s, type: %s", boxId, type); + std::string result{type}; + free(const_cast<char*>(type)); + return result; +} + +BoxInfoPtr BoxDaemonImpl::initializeBoxInfo(ProviderEventArgPtr arg) +{ + LogD("enter"); + + if (!arg) { + return BoxInfoPtr(); + } + + if (!arg->pkgname || !arg->id) { + LogD("pkgname or id don't exist"); + return BoxInfoPtr(); + } + + std::string type = getBoxType(arg->pkgname); + if (type.empty()) { + return BoxInfoPtr(); + } + BoxInfoPtr infoPtr = BoxInfoPtr(new BoxInfo(type, arg->pkgname, arg->id)); + + return infoPtr; +} + +std::string BoxDaemonImpl::getBoxIdFromService(service_h service) +{ + LogD("enter"); + + int ret; + char* serviceUri = NULL; + ret = service_get_uri(service, &serviceUri); + if (ret != SERVICE_ERROR_NONE) { + LogD("no box uri"); + return std::string(); + } + + std::string uri(serviceUri); + delete[] serviceUri; + + if(uri.compare(0, strlen(SERVICE_BOX_SERVICE_SCHEME), SERVICE_BOX_SERVICE_SCHEME)) { + // uri is not box-service scheme + return std::string(); + } + + std::string boxId = uri.substr(strlen(SERVICE_BOX_SERVICE_SCHEME)); + return boxId; +} + +bool BoxDaemonImpl::isServiceCallerBoxOwner(service_h service) +{ + LogD("enter"); + + int ret; + + std::string boxId = getBoxIdFromService(service); + if (boxId.empty()) { + LogD("error box-id"); + return false; + } + + // check if caller is owner of this box + const char* appId = web_provider_livebox_get_app_id(boxId.c_str()); + if (!appId) { + return false; + } + std::string ownerAppId(appId); + delete[] appId; + + char* caller = NULL; + ret = service_get_caller(service, &caller); + if (ret != SERVICE_ERROR_NONE) { + ret = service_get_extra_data( + service, SERVICE_ALARM_CALLER_KEY, &caller); + if (ret != SERVICE_ERROR_NONE) { + LogD("failed to get caller's appid from service"); + return false; + } + } + std::string callerAppId(caller); + + // release strings + delete[] caller; + + if (ownerAppId != callerAppId) { + LogD("caller is not matched with owner of requested box"); + return false; + } + + return true; +} + +BoxInfoPtr BoxDaemonImpl::handleOperationUpdate(service_h service) +{ + LogD("enter"); + + if (!isServiceCallerBoxOwner(service)) { + return BoxInfoPtr(); + } + + std::string boxId = getBoxIdFromService(service); + if (boxId.empty()) { + LogD("error box-id"); + return BoxInfoPtr(); + } + + char* appContentInfo = NULL; + service_get_extra_data(service, SERVICE_CONTENT_INFO_KEY, &appContentInfo); + + std::string type(getBoxType(boxId.c_str())); + if (type.empty()) { + LogD("no type for this box"); + delete[] appContentInfo; + return BoxInfoPtr(); + } + + BoxInfoPtr info = BoxInfoPtr(new BoxInfo(type, boxId, "")); + if (appContentInfo) { + LogD("service content info: %s", appContentInfo); + info->appContentInfo = std::string(appContentInfo); + } + + // release string + delete[] appContentInfo; + + return info; +} + +int BoxDaemonImpl::requestUpdateAll(void) +{ + LogD("enter"); + + BoxInfoPtr info = BoxInfoPtr(new BoxInfo()); + JobInfo* jobInfo = new JobInfo(REQUEST_CMD_UPDATE_ALL, info, this); + + ecore_job_add(requestBoxJobCallback, jobInfo); + return 0; +} + +std::vector<BoxInfoPtr> BoxDaemonImpl::handleOperationRemove(service_h service) +{ + LogD("enter"); + + char* appId = NULL; + service_get_extra_data(service, SERVICE_REMOVE_APPID_KEY, &appId); + LogD("request appid: %s", appId); + + // check if this appId has dynamic boxes + int boxCount = 0; + char** boxIdList = web_provider_livebox_get_box_id_list(appId, &boxCount); + if (!boxIdList) { + return std::vector<BoxInfoPtr>(); + } + + std::vector<BoxInfoPtr> boxInfoPtrContainer; + for (int i = 0; i < boxCount; i++) { + // get plugin type of each box id + std::string type(getBoxType(boxIdList[i])); + if (type.empty()) { + LogD("no type for this box: %s", boxIdList[i]); + continue; + } + + BoxInfoPtr info = BoxInfoPtr(new BoxInfo(type, boxIdList[i], "")); + boxInfoPtrContainer.push_back(info); + } + + return boxInfoPtrContainer; +} + +Eina_Bool BoxDaemonImpl::pingToMasterCallback(void* data) +{ + LogD("enter"); + UNUSED_PARAM(data); + + provider_send_ping(); + + return ECORE_CALLBACK_RENEW; +} + +void BoxDaemonImpl::requestBoxJobCallback(void* data) +{ + JobInfo* jobInfo = static_cast<JobInfo*>(data); + if (!jobInfo) { + LogD("no information for job"); + return; + } + + // just for debugging + //volatile int flag = 0; + //while(flag == 0) {;} + + // request box job! + jobInfo->daemonImpl->m_pluginConnector->requestCommand( + jobInfo->cmdType, jobInfo->boxInfo); + + delete jobInfo; +} + +int BoxDaemonImpl::requestUpdateAllCallback(void* data) +{ + LogD("enter"); + BoxDaemonImpl* This = static_cast<BoxDaemonImpl*>(data); + return This->requestUpdateAll(); +} + +int BoxDaemonImpl::requestLowMemoryCallback(void* data) +{ + LogD("enter"); + UNUSED_PARAM(data); + + // terminate box daemon and revive + elm_exit(); + return 0; +} + +void BoxDaemonImpl::requestUpdateAllCallback(keynode_t* key, void* data) +{ + LogD("enter"); + UNUSED_PARAM(key); + + BoxDaemonImpl* This = static_cast<BoxDaemonImpl*>(data); + This->requestUpdateAll(); +} + +void BoxDaemonImpl::requestUpdateAppBoxCallback(keynode_t* key, void* data) +{ + LogD("enter"); + UNUSED_PARAM(key); + + BoxDaemonImpl* This = static_cast<BoxDaemonImpl*>(data); + BoxInfoPtr info = BoxInfoPtr(new BoxInfo()); + JobInfo* jobInfo = new JobInfo(REQUEST_CMD_UPDATE_APPBOX, info, This); + + ecore_job_add(requestBoxJobCallback, jobInfo); +} diff --git a/src_wearable/Daemon/BoxDaemonImpl.h b/src_wearable/Daemon/BoxDaemonImpl.h new file mode 100755 index 0000000..c82edfd --- /dev/null +++ b/src_wearable/Daemon/BoxDaemonImpl.h @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file BoxDaemonImpl.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef BOX_DAEMON_IMPL_H +#define BOX_DAEMON_IMPL_H + +#include <string> +#include <memory> +#include <vector> + +#include <app.h> +#include <provider.h> +#include <Eina.h> +#include <Ecore.h> +#include <vconf.h> + +#include <Plugin/box_plugin_interface.h> +#include <Core/BoxData.h> + +// forward declaration +class IBoxManager; +class IBoxPluginConnector; + +class BoxDaemonImpl { + public: + bool start(std::string& name); + bool stop(); + bool handleAppService(service_h service); + + public: + explicit BoxDaemonImpl(); + ~BoxDaemonImpl(); + + private: + // type definition + typedef struct event_arg ProviderEventArg; + typedef ProviderEventArg* ProviderEventArgPtr; + typedef struct event_handler ProviderCallbacks; + typedef ProviderCallbacks* ProviderCallbacksPtr; + + // livebox's provider callbacks + static int connectedCallback(ProviderEventArgPtr arg, void* data); + static int disconnectedCallback(ProviderEventArgPtr arg, void* data); + static int boxCreateCallback( + ProviderEventArgPtr arg, + int* width, int* height, + double* priority, void* data); + static int boxReCreateCallback(ProviderEventArgPtr arg, void* data); + static int boxDestroyCallback(ProviderEventArgPtr arg, void* data); + static int pdCreateCallback(ProviderEventArgPtr arg, void* data); + static int pdDestroyCallback(ProviderEventArgPtr arg, void* data); + static int clickedCallback(ProviderEventArgPtr arg, void* data); + static int boxResizeCallback(ProviderEventArgPtr arg, void* data); + static int boxPauseCallback(ProviderEventArgPtr arg, void* data); + static int boxResumeCallback(ProviderEventArgPtr arg, void* data); + static int pauseCallback(ProviderEventArgPtr arg, void* data); + static int resumeCallback(ProviderEventArgPtr arg, void* data); + static int boxPeriodChangeCallback(ProviderEventArgPtr arg, void* data); + static int boxUpdateCallback(ProviderEventArgPtr arg, void* data); + // callback for app-core event + static int requestUpdateAllCallback(void* data); + static int requestLowMemoryCallback(void* data); + // callback for vconf event + static void requestUpdateAllCallback(keynode_t* key, void* data); + static void requestUpdateAppBoxCallback(keynode_t* key, void* data); + + // common private functions + void setProviderCallbacks(ProviderCallbacks& callbacks); + std::string getBoxType(const char* boxId); + BoxInfoPtr initializeBoxInfo(ProviderEventArgPtr arg); + int requestUpdateAll(void); + + // functions for handling appcontrol per operation + std::string getBoxIdFromService(service_h service); + bool isServiceCallerBoxOwner(service_h service); + BoxInfoPtr handleOperationUpdate(service_h service); + std::vector<BoxInfoPtr> handleOperationRemove(service_h service); + + // callback for ping to master daemon + static Eina_Bool pingToMasterCallback(void* data); + + // callback for requested jobs of boxes + static void requestBoxJobCallback(void* data); + + // members + std::string m_daemonName; + Ecore_Timer* m_pingTimer; + std::shared_ptr<IBoxPluginConnector> m_pluginConnector; +}; + +struct JobInfo { + request_cmd_type cmdType; + BoxInfoPtr boxInfo; + BoxDaemonImpl* daemonImpl; + + JobInfo(request_cmd_type cmdType, + BoxInfoPtr boxInfo, + BoxDaemonImpl* daemonImpl) : + cmdType(cmdType), + boxInfo(boxInfo), + daemonImpl(daemonImpl) + { + }; +}; + + +#endif //BOX_DAEMON_IMPL_H + diff --git a/src_wearable/Daemon/BoxDaemonUtil.cpp b/src_wearable/Daemon/BoxDaemonUtil.cpp new file mode 100644 index 0000000..7df1a0f --- /dev/null +++ b/src_wearable/Daemon/BoxDaemonUtil.cpp @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file BoxDaemonUtil.cpp + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#include <sstream> +#include <string> +#include <memory> +#include <time.h> +#include <app_service.h> +#include <Core/Util/Log.h> +#include <API/web_provider_livebox_info.h> +#include "BoxDaemonUtil.h" + +const std::string BoxDaemonUtil::boxIdKey("box-id"); +const std::string BoxDaemonUtil::instanceIdKey("instance-id"); + +bool BoxDaemonUtil::launchApplication(std::string& boxId, std::string& instanceId) +{ + LogD("enter"); + + std::shared_ptr<const char> appId(web_provider_livebox_get_app_id(boxId.c_str())); + if (!appId) { + LogD("no appid of %s", boxId.c_str()); + return false; + } + + service_h handle = NULL; + int ret = SERVICE_ERROR_NONE; + + ret = service_create(&handle); + if (ret != SERVICE_ERROR_NONE && !handle) { + LogD("failed to create service"); + return false; + } + + ret = service_set_package(handle, appId.get()); + if (ret != SERVICE_ERROR_NONE) { + LogD("failed to set package"); + service_destroy(handle); + return false; + } + + service_add_extra_data(handle, boxIdKey.c_str(), boxId.c_str()); + service_add_extra_data(handle, instanceIdKey.c_str(), instanceId.c_str()); + + ret = service_send_launch_request(handle, NULL, NULL); + if (ret != SERVICE_ERROR_NONE) { + LogD("failed to launch package"); + service_destroy(handle); + return false; + } + + service_destroy(handle); + LogD("success to launch app of %s", boxId.c_str()); + + return true; +} + +std::string BoxDaemonUtil::createWebInstanceId(std::string& boxId) +{ + LogD("enter"); + std::ostringstream webInstanceId; + + webInstanceId << boxId; + + struct timespec timeSpec; + if (clock_gettime(CLOCK_REALTIME, &timeSpec) < 0) { + return std::string(); + } + + webInstanceId << "." << timeSpec.tv_sec << timeSpec.tv_nsec; + LogD("Web instance id: %s", webInstanceId.str().c_str()); + return webInstanceId.str(); +} diff --git a/src_wearable/Daemon/BoxDaemonUtil.h b/src_wearable/Daemon/BoxDaemonUtil.h new file mode 100644 index 0000000..3d58396 --- /dev/null +++ b/src_wearable/Daemon/BoxDaemonUtil.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file BoxDaemonUtil.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef BOX_DAEMON_UTIL_H +#define BOX_DAEMON_UTIL_H + +#include <string> + +class BoxDaemonUtil { + public: + static bool launchApplication(std::string& boxId, std::string& instanceId); + static std::string createWebInstanceId(std::string& boxId); + + private: + static const std::string boxIdKey; + static const std::string instanceIdKey; + +}; + +#endif // BOX_DAEMON_UTIL_H diff --git a/src_wearable/Daemon/CMakeLists.txt b/src_wearable/Daemon/CMakeLists.txt new file mode 100644 index 0000000..2384519 --- /dev/null +++ b/src_wearable/Daemon/CMakeLists.txt @@ -0,0 +1,66 @@ +# Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved +# +# Licensed under the Flora License, Version 1.1 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://floralicense.org/license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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) + +SET(TARGET_NAME ${TARGET_DAEMON}) +SET(DEPS ${TARGET_NAME}_DEPS) + +PKG_CHECK_MODULES(${DEPS} + aul + bundle + appcore-efl + elementary + ecore-x + provider + livebox-service + capi-appfw-application + dlog + REQUIRED +) +ADD_DEFINITIONS(${${DEPS}_CFLAGS}) + +SET(SRCS + ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/BoxDaemon.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/BoxDaemonImpl.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/BoxDaemonUtil.cpp +) + +SET(HEADERS + ${${DEPS}_INCLUDE_DIRS} + ${CMAKE_CURRENT_SOURCE_DIR} +) +INCLUDE_DIRECTORIES(${HEADERS}) + +ADD_EXECUTABLE(${TARGET_NAME} ${SRCS}) + +SET_TARGET_PROPERTIES(${TARGET_NAME} PROPERTIES + COMPILE_FLAGS -fPIC + LINK_FLAGS "-Wl,--as-needed -Wl,--hash-style=both" +) + +TARGET_LINK_LIBRARIES(${TARGET_NAME} + ${${DEPS}_LDFLAGS} "-ldl -lcap -lrt" + ${${DEPS}_LIBRARIES} + ${TARGET_PLUGIN} + ${TARGET_CORE} + ${TARGET_API} +) + +INSTALL(TARGETS ${TARGET_NAME} + DESTINATION /usr/apps/livebox.${PROJECT_NAME}/bin + PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE + GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE +) diff --git a/src_wearable/Daemon/main.cpp b/src_wearable/Daemon/main.cpp new file mode 100755 index 0000000..85b1940 --- /dev/null +++ b/src_wearable/Daemon/main.cpp @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file main.cpp + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ + +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/capability.h> +#include <Elementary.h> +#include <aul.h> +#include <app.h> +#include <Core/Util/Log.h> +#include <Core/Util/Util.h> +#include "BoxDaemon.h" + + +// declarations +static BoxDaemon boxDaemon; +static bool isDaemonReleased = false; + +static void atExitCallback() +{ + LogD("enter"); + if (isDaemonReleased) { + return; + } + + // this callback is called due to abnormal exit() + LogD("release daemon resources explicitly"); + boxDaemon.stop(); +} + +static bool appCreateCallback(void *data) +{ + LogD("app create"); + UNUSED_PARAM(data); + + elm_config_preferred_engine_set("software_x11"); + return true; +} + +static void appTerminateCallback(void *data) +{ + BoxDaemon *boxDaemon = static_cast<BoxDaemon *>(data); + boxDaemon->stop(); + isDaemonReleased = true; +} + +static void appPauseCallback(void *data) +{ + LogD("app pasue"); + UNUSED_PARAM(data); +} + +static void appResumeCallback(void *data) +{ + LogD("app resume"); + UNUSED_PARAM(data); +} + +static void appServiceCallback(service_h service, void *data) +{ + LogD("app service"); + + int ret; + char* name; + + BoxDaemon *boxDaemon = static_cast<BoxDaemon*>(data); + ret = service_get_extra_data(service, "name", &name); + + // check if web-provider is launched, or not + if (ret == SERVICE_ERROR_NONE) { + std::string daemonName(name); + if(!(boxDaemon->start(daemonName))) { + LogD("daemon failed to start"); + elm_exit(); + } + atexit(atExitCallback); + return; + } + + boxDaemon->handleAppService(service); +} + +static bool grantProcessCapability() +{ + cap_user_header_t header; + cap_user_data_t data; + + header = static_cast<cap_user_header_t>(malloc(sizeof(*header))); + data = static_cast<cap_user_data_t>(calloc(sizeof(*data), _LINUX_CAPABILITY_U32S_3)); + + header->pid = getpid(); + header->version = _LINUX_CAPABILITY_VERSION_3; + + // read already granted capabilities of this process + if (capget(header, data) < 0) { + LogD("capget error"); + free(header); + free(data); + return false; + } + + // set only inheritable bit for CAP_MAC_ADMIN to '1' + data[CAP_TO_INDEX(CAP_MAC_ADMIN)].inheritable |= CAP_TO_MASK(CAP_MAC_ADMIN); + + // remove capabilities not needed any more + data[CAP_TO_INDEX(CAP_MAC_ADMIN)].permitted &= ~CAP_TO_MASK(CAP_MAC_ADMIN); + data[CAP_TO_INDEX(CAP_MAC_ADMIN)].effective &= ~CAP_TO_MASK(CAP_MAC_ADMIN); + data[CAP_TO_INDEX(CAP_SETPCAP)].permitted &= ~CAP_TO_MASK(CAP_SETPCAP); + data[CAP_TO_INDEX(CAP_SETPCAP)].effective &= ~CAP_TO_MASK(CAP_SETPCAP); + + bool ret = true; + if (capset(header, data) < 0) { + LogD("capset error"); + ret = false; + } + + free(header); + free(data); + + return ret; +} + +int main (int argc, char *argv[]) +{ + // set inheritable bit for CAP_MAC_ADMIN + // so that WebProcess will have CAP_MAC_ADMIN capability + if (!grantProcessCapability()) { + return -1; + } + + // set the appcore callbacks + app_event_callback_s ops; + memset(&ops, 0x00, sizeof(app_event_callback_s)); + ops.create = appCreateCallback; + ops.terminate = appTerminateCallback; + ops.pause = appPauseCallback; + ops.resume = appResumeCallback; + ops.service = appServiceCallback; + + // start appcore + int ret = app_efl_main(&argc, &argv, &ops, &boxDaemon); + return ret; +} diff --git a/src_wearable/Plugin/AppBoxPlugin/AppBoxManager.cpp b/src_wearable/Plugin/AppBoxPlugin/AppBoxManager.cpp new file mode 100755 index 0000000..ae41127 --- /dev/null +++ b/src_wearable/Plugin/AppBoxPlugin/AppBoxManager.cpp @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file AppBoxManager.cpp + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#include <map> +#include <ail.h> +#include <ewk_context.h> +#include <core_module.h> +#include <Plugin/IBoxPluginFactory.h> +#include <Core/BoxData.h> +#include <Core/BoxManager.h> +#include <Core/IBox.h> +#include <Core/Util/Log.h> +#include <API/web_provider_livebox_info.h> +#include "AppBoxManager.h" + +static const std::string bundlePath("/usr/lib/libwrt-injected-bundle.so"); + +AppBoxManager::AppBoxManager(IBoxPluginFactoryPtr factory) + : BoxManager(factory) +{ + bool ret = WRT::CoreModuleSingleton::Instance().Init(); + if (!ret) { + throw; // throw exeception + } +} + +AppBoxManager::~AppBoxManager() +{ +} + +bool AppBoxManager::requestAddBox(BoxInfoPtr boxInfo, EwkContextPtr ewkContext) +{ + const char* appId = + web_provider_livebox_get_app_id(boxInfo->boxId.c_str()); + + if (!appId) { + LogD("no appid of %s", boxInfo->boxId.c_str()); + return false; + } + + std::string appIdStr(appId); + delete appId; + + auto it = m_ewkContextMap.find(appIdStr); + if (it == m_ewkContextMap.end()) { + ewkContext = getAvailableEwkContext(appIdStr); + insertContextMap(appIdStr, ewkContext); + } else { + ewkContext = it->second; + } + + if (!BoxManager::requestAddBox(boxInfo, ewkContext)) { + return false; + } + + return true; +} + +void AppBoxManager::updateEwkContext(std::string& boxId) +{ + LogD("enter"); + const char* appId = web_provider_livebox_get_app_id(boxId.c_str()); + if (!appId) { + LogD("no appid of %s", boxId.c_str()); + return; + } + + std::string appIdStr(appId); + delete appId; + + int count = BoxManager::getBoxCount(appIdStr); + LogD("count: %d", count); + if (!count) { + LogD("%s's ewk context removed", appIdStr.c_str()); + // remove ewk context + eraseContextMap(appIdStr); + } +} + +EwkContextPtr AppBoxManager::getAvailableEwkContext(const std::string& appId) +{ + + // get the base executable path + std::string baseExecutablePath = getBaseExecutablePath(appId); + if (baseExecutablePath.empty()) { + return EwkContextPtr(); + } + + // get web process path for this box + std::string webProcessPath = baseExecutablePath + ".d-box"; + + // get plugin process path for this box + std::string pluginProcessPath = baseExecutablePath + ".npruntime"; + + // box manager should set webprocess path as value of 'WEB_PROCESS_PATH' + // before calling ewk_context_new_with_injected_bundle_path(). + setenv("WEB_PROCESS_EXECUTABLE_PATH", webProcessPath.c_str(), 1); + setenv("PLUGIN_PROCESS_EXECUTABLE_PATH", pluginProcessPath.c_str(), 1); + + EwkContextPtr newEwkContext( + ewk_context_new_with_injected_bundle_path(bundlePath.c_str()), + BoxManager::EwkContextDeleter()); + + // unset the following env variables not to affect other ewk context creation + unsetenv("WEB_PROCESS_EXECUTABLE_PATH"); + unsetenv("PLUGIN_PROCESS_EXECUTABLE_PATH"); + + return newEwkContext; +} + +void AppBoxManager::insertContextMap(std::string& appId, EwkContextPtr ewkContext) +{ + m_ewkContextMap.insert(EwkContextMapPair(appId, ewkContext)); +} + +void AppBoxManager::eraseContextMap(std::string& appId) +{ + m_ewkContextMap.erase(appId); +} + +std::string AppBoxManager::getBaseExecutablePath(const std::string& appId) +{ + ail_error_e ret; + ail_appinfo_h handle = NULL; + + char* retStr = NULL; + ret = ail_get_appinfo(appId.c_str(), &handle); + if (ret != AIL_ERROR_OK) { + return std::string(); + } + + ret = ail_appinfo_get_str(handle, AIL_PROP_X_SLP_EXE_PATH, &retStr); + if (ret != AIL_ERROR_OK || !retStr) { + return std::string(); + } + + std::string basePath(retStr); + + ret = ail_destroy_appinfo(handle); + if (ret != AIL_ERROR_OK) { + return std::string(); + } + + return basePath; +} diff --git a/src_wearable/Plugin/AppBoxPlugin/AppBoxManager.h b/src_wearable/Plugin/AppBoxPlugin/AppBoxManager.h new file mode 100644 index 0000000..7ef82a6 --- /dev/null +++ b/src_wearable/Plugin/AppBoxPlugin/AppBoxManager.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file AppBoxManager.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef APP_BOX_MANAGER_H +#define APP_BOX_MANAGER_H + +#include <Core/IBox.h> +#include <Core/IBoxManager.h> +#include <Core/BoxManager.h> +#include <Core/BoxData.h> +#include <Plugin/IBoxPluginFactory.h> + +class AppBoxManager: public BoxManager { + public: + static IBoxManagerPtr create(IBoxPluginFactoryPtr factory) + { + return IBoxManagerPtr(new AppBoxManager(factory)); + }; + ~AppBoxManager(); + + private: + // BoxManager implementation + bool requestAddBox(BoxInfoPtr boxInfo, EwkContextPtr ewkContext); + void updateEwkContext(std::string& boxId); + + EwkContextPtr getAvailableEwkContext(const std::string& appId); + void insertContextMap(std::string& appId, EwkContextPtr ewkContext); + void eraseContextMap(std::string& appId); + std::string getBaseExecutablePath(const std::string& appId); + explicit AppBoxManager(IBoxPluginFactoryPtr factory); + + // members + typedef std::map<std::string, EwkContextPtr> EwkContextMap; + typedef std::pair<std::string, EwkContextPtr> EwkContextMapPair; + EwkContextMap m_ewkContextMap; +}; + + +#endif // APP_BOX_MANAGER_H diff --git a/src_wearable/Plugin/AppBoxPlugin/AppBoxPdHelper.cpp b/src_wearable/Plugin/AppBoxPlugin/AppBoxPdHelper.cpp new file mode 100644 index 0000000..46e0fb9 --- /dev/null +++ b/src_wearable/Plugin/AppBoxPlugin/AppBoxPdHelper.cpp @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file AppBoxPdHelper.cpp + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#include <string> +#include <Evas.h> +#include <ewk_view.h> +#include <Core/Util/Log.h> +#include "AppBoxPdHelper.h" + +AppBoxPdHelper::AppBoxPdHelper(Evas_Object* pdWin) + : m_win(pdWin) + , m_boxWebView() + , m_pdWebView() + , m_opened(false) +{ +} + +AppBoxPdHelper::~AppBoxPdHelper() +{ +} + +void AppBoxPdHelper::startOpen() +{ + LogD("enter"); +} + +void AppBoxPdHelper::finishOpen(Evas_Object* child) +{ + LogD("enter"); + m_opened = true; + setPdWebView(child); +} + +void AppBoxPdHelper::close() +{ + LogD("enter"); +} + +void AppBoxPdHelper::setBoxWebView(Evas_Object* webview) +{ + LogD("enter"); + m_boxWebView = webview; +} + +void AppBoxPdHelper::setPdWebView(Evas_Object* webview) +{ + LogD("enter"); + m_pdWebView = webview; +} + +Evas_Object* AppBoxPdHelper::getBoxWebView() const +{ + LogD("enter"); + return m_boxWebView; +} + +Evas_Object* AppBoxPdHelper::getPdWebView() const +{ + LogD("enter"); + return m_pdWebView; +} + +Evas* AppBoxPdHelper::getPdCanvas() const +{ + LogD("enter"); + return evas_object_evas_get(m_win); +} + +bool AppBoxPdHelper::isPdOpened() const +{ + LogD("enter"); + return m_opened; +} diff --git a/src_wearable/Plugin/AppBoxPlugin/AppBoxPdHelper.h b/src_wearable/Plugin/AppBoxPlugin/AppBoxPdHelper.h new file mode 100644 index 0000000..ae49863 --- /dev/null +++ b/src_wearable/Plugin/AppBoxPlugin/AppBoxPdHelper.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file AppBoxPdHelper.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ + +#ifndef APP_BOX_PD_HELPER_H +#define APP_BOX_PD_HELPER_H + +#include <string> +#include <Evas.h> +#include <Core/View/IPdHelper.h> + +class AppBoxPdHelper: public IPdHelper { + public: + static IPdHelperPtr create(Evas_Object* pdWin) + { + return IPdHelperPtr(new AppBoxPdHelper(pdWin)); + } + virtual void startOpen(); + virtual void finishOpen(Evas_Object* child); + virtual void close(); + virtual void setBoxWebView(Evas_Object* webview); + virtual void setPdWebView(Evas_Object* webview); + virtual Evas_Object* getBoxWebView() const; + virtual Evas_Object* getPdWebView() const; + virtual Evas* getPdCanvas() const; + virtual bool isPdOpened() const; + virtual ~AppBoxPdHelper(); + + private: + AppBoxPdHelper(Evas_Object* pdWin); + + //members + Evas_Object* m_win; + Evas_Object* m_boxWebView; + Evas_Object* m_pdWebView; + bool m_opened; +}; + +#endif // APP_BOX_PD_HELPER_H diff --git a/src_wearable/Plugin/AppBoxPlugin/AppBoxPluginFactory.cpp b/src_wearable/Plugin/AppBoxPlugin/AppBoxPluginFactory.cpp new file mode 100644 index 0000000..58f149c --- /dev/null +++ b/src_wearable/Plugin/AppBoxPlugin/AppBoxPluginFactory.cpp @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file AppBoxPluginFactory.cpp + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#include <string> +#include <memory> +#include <Core/View/IRenderView.h> +#include <Core/BoxData.h> +#include "AppBoxRenderView.h" +#include "AppBoxPluginFactory.h" + +IRenderViewPtr AppBoxPluginFactory::createRenderView( + std::shared_ptr<BoxInfo> boxInfo, + std::shared_ptr<Ewk_Context> ewkContext) +{ + return AppBoxRenderView::create(boxInfo, ewkContext); +} diff --git a/src_wearable/Plugin/AppBoxPlugin/AppBoxPluginFactory.h b/src_wearable/Plugin/AppBoxPlugin/AppBoxPluginFactory.h new file mode 100644 index 0000000..e54d409 --- /dev/null +++ b/src_wearable/Plugin/AppBoxPlugin/AppBoxPluginFactory.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file AppBoxPluginFactory.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef APP_BOX_PLUGIN_FACTORY_H +#define APP_BOX_PLUGIN_FACTORY_H + +#include <string> +#include <memory> +#include <Plugin/IBoxPluginFactory.h> +#include <Core/View/IRenderView.h> +#include <Core/Buffer/IRenderBuffer.h> +#include <ewk_context.h> +#include <Evas.h> + +// forward declaration +struct BoxInfo; + +class AppBoxPluginFactory: public IBoxPluginFactory { + public: + IRenderViewPtr createRenderView( + std::shared_ptr<BoxInfo> boxInfo, + std::shared_ptr<Ewk_Context> ewkContext); + + AppBoxPluginFactory() {}; + ~AppBoxPluginFactory() {}; +}; + +#endif //APP_BOX_PLUGIN_FACTORY_H diff --git a/src_wearable/Plugin/AppBoxPlugin/AppBoxRenderView.cpp b/src_wearable/Plugin/AppBoxPlugin/AppBoxRenderView.cpp new file mode 100755 index 0000000..6513973 --- /dev/null +++ b/src_wearable/Plugin/AppBoxPlugin/AppBoxRenderView.cpp @@ -0,0 +1,950 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file AppBoxRenderView.cpp + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#include "config.h" +#include "AppBoxRenderView.h" + +#include <sys/types.h> +#include <unistd.h> +#include <string> +#include <fstream> +#include <functional> +#include <streambuf> +#include <ail.h> +#include <aul.h> +#include <Eina.h> +#include <Evas.h> +#include <Ecore.h> +#include <Elementary.h> +#include <EWebKit2.h> +#include <ewk_view.h> +#include <ewk_context.h> +#include <ewk_settings.h> +#include <livebox-service.h> +#include <i_runnable_widget_object.h> +#include <core_module.h> +#include <provider.h> +#include <API/web_provider_livebox_info.h> +#include <Core/BoxData.h> +#include <Core/View/IPdHelper.h> +#include <Core/View/PdHelper.h> +#include <Core/Util/Log.h> +#include <Core/Util/Util.h> + +#include "AppBoxPdHelper.h" + + +#define RENDER_MAX_TIME 30.0 +#define RENDER_MAX_TIME_FOR_INSPECTOR 1200.0 +#define SNAPSHOT_REMOVE_TIME 0.5 +#define TOUCH_MAX_WAIT_TIME 10.0 +#define WEB_DBOX_OBJ_MOVE_TO_OUTSIDE_POINT_VALUE -10000 + +// injection javascript file regarding creating js object used by box and pd +static const std::string injectionFile("/usr/share/web-provider/injection.js"); +static const std::string consoleMessageLogTag("ConsoleMessage"); +static const std::string jsRegisterBoxInfoFunction( + "webprovider.registerAppWidgetContextInfo"); + +AppBoxRenderView::AppBoxRenderView( + BoxInfoPtr boxInfo, + EwkContextPtr ewkContext) + : RenderView(boxInfo, false) + , m_appId() + , m_boxId() + , m_instanceId() + , m_contentInfo() + , m_ewkContext(ewkContext) + , m_boxRenderInfo() + , m_boxWrt() + , m_pdWrt() + , m_boxRenderBuffer() + , m_pdRenderBuffer() + , m_boxSnapshot() + , m_boxRenderTimer() + , m_boxTouchTimer() + , m_boxRemoveSnapShotTimer() + , m_pdHelper() + , m_boxIcon() + , m_pdFastOpen(false) + , m_boxFinishLoad(false) + , m_boxFrameRendered(false) + , m_boxWaitFrameRender(false) + , m_isTouchableBox(false) + , m_boxWrt_isSuspended(false) + , m_showed(false) + , m_showIcon(false) +{ + LogD("enter"); + + // member initialization + m_boxId = boxInfo->boxId; + m_instanceId = boxInfo->instanceId; + m_contentInfo = boxInfo->contentInfo; + m_appId = getAppId(m_boxId); + if (m_appId.empty()) { + throw; //exception throw! + } + + + // get box render buffer + m_boxRenderBuffer = getBoxBuffer(); + + if (!m_showIcon) { + ail_appinfo_h handle; + ail_error_e ret; + char *icon; + ret = ail_get_appinfo(m_appId.c_str(), &handle); + if (ret != AIL_ERROR_OK) { + LogE("[%s] DB_FAILED(0x) : failed to get the app-info", __FUNCTION__); + } else { + ail_appinfo_get_str(handle, AIL_PROP_ICON_STR, &icon); + } +#if ENABLE(SHOW_PRE_ICON) + showIcon(icon, boxInfo->boxWidth, boxInfo->boxHeight); +#endif + ail_destroy_appinfo(handle); + } + // use fastopen to default + // m_pdFastOpen = web_provider_livebox_get_pd_fast_open(m_boxId.c_str()) ? true : false; + m_pdFastOpen = true; + m_isTouchableBox = + web_provider_livebox_get_mouse_event(m_boxId.c_str()) ? true : false; +} + +AppBoxRenderView::~AppBoxRenderView() +{ + LogD("enter"); + + destroyWrtCore(m_boxWrt); + destroyWrtCore(m_pdWrt); +} + +void AppBoxRenderView::showBox(RenderInfoPtr boxRenderInfo) +{ + LogD("enter"); + + // stop updating render buffer + m_boxRenderBuffer->stopCanvasUpdate(); + + if (m_boxRenderTimer) { + // delete already running timer + stopRenderBox(); + } + + // delete touch timer + if (m_isTouchableBox) { + deleteTimer(&m_boxTouchTimer); + } + + // set boxFinishLoad and m_boxFrameRendered to false + m_boxFinishLoad = false; + m_boxFrameRendered = false; + m_boxWaitFrameRender = false; + + // copy to url + std::string boxStartUrl = getStartUrl(URL_TYPE_BOX, boxRenderInfo->defaultUrlParams); + if (m_boxWrt) { + LogD("existing wrt core is removed"); + destroyBoxWrtCore(); + } + + m_boxWrt = createWrtCore( + URL_TYPE_BOX, boxStartUrl, + boxRenderInfo->window, m_ewkContext); + m_boxWrt_isSuspended = false; + + // in case of showing box by request of pd open + if (m_pdHelper) { + m_pdHelper->setBoxWebView(m_boxWrt->GetCurrentWebview()); + } + + // resize webview fitted to width, height of Box + evas_object_resize( + m_boxWrt->GetCurrentWebview(), + boxRenderInfo->width, + boxRenderInfo->height); + + showSnapShot(); + evas_object_show(m_boxWrt->GetCurrentWebview()); + // webview window move to outside of viewport because of overlap issue with snapshot image + evas_object_move(m_boxWrt->GetCurrentWebview(), WEB_DBOX_OBJ_MOVE_TO_OUTSIDE_POINT_VALUE, WEB_DBOX_OBJ_MOVE_TO_OUTSIDE_POINT_VALUE); + + m_boxWrt->Show(); + m_boxRenderInfo = boxRenderInfo; + + // start timer for clearing existing snapshot in case of only pd open + addTimer(&m_boxRemoveSnapShotTimer, + SNAPSHOT_REMOVE_TIME, removeBoxSnapShotTimerCallback); + m_showed = true; +} + +AppBoxRenderView::WrtCorePtr AppBoxRenderView::createWrtCore( + UrlType type, std::string& startUrl, + Evas_Object* win, EwkContextPtr ewkContext) +{ + LogD("enter"); + + WrtCorePtr wrt; + wrt = WRT::CoreModuleSingleton:: + Instance().getRunnableWidgetObject(m_appId); + + // prepare webview + if (startUrl.empty()) { + LogD("no start url"); + return WrtCorePtr(); + } + wrt->PrepareView(startUrl, win, ewkContext.get()); + wrt->CheckBeforeLaunch(); + + // set callback functions of RunnableWidgetObject + WRT::UserDelegatesPtr cbs(new WRT::UserDelegates); + using namespace std::placeholders; + cbs->loadStartedCallback = std::bind(&AppBoxRenderView::startLoadCallback, this, _1, _2); + if (type == URL_TYPE_BOX) { + cbs->loadFinishedCallback = std::bind(&AppBoxRenderView::finishBoxLoadCallback, this, _1, _2); + } else { + cbs->loadFinishedCallback = std::bind(&AppBoxRenderView::finishPdLoadCallback, this, _1, _2); + } + + cbs->setWebviewCallback = std::bind(&AppBoxRenderView::setBufferCallback, this, _1); + cbs->unsetWebviewCallback = std::bind(&AppBoxRenderView::unsetBufferCallback, this, _1); + + cbs->policyNavigationDecideCallback = std::bind(&AppBoxRenderView::decideNavigationCallback, this, _1, _2); + cbs->processCrashedCallback = std::bind(&AppBoxRenderView::crashWebProcessCallback, this, _1, _2); + cbs->consoleMessageCallback = std::bind(&AppBoxRenderView::consoleMessageCallback, this, _1, _2); + wrt->SetUserDelegates(cbs); + + // set basic webview setting + setWebViewBasicSetting(wrt->GetCurrentWebview()); + + // only box type needed + if (type == URL_TYPE_BOX) { + Ewk_Settings* setting = ewk_view_settings_get(wrt->GetCurrentWebview()); + ewk_settings_link_effect_enabled_set(setting, EINA_FALSE); + } + + return wrt; +} + +void AppBoxRenderView::destroyBoxWrtCore() +{ + LogD("enter"); + + // stop updating render buffer + m_boxRenderBuffer->stopCanvasUpdate(); + deleteTimer(&m_boxRenderTimer); + deleteTimer(&m_boxRemoveSnapShotTimer); + destroyWrtCore(m_boxWrt); + m_boxWrt.reset(); + + // temp + m_boxWrt_isSuspended = false; +} + +void AppBoxRenderView::destroyPdWrtCore() +{ + LogD("enter"); + + destroyWrtCore(m_pdWrt); + m_pdWrt.reset(); +} + +void AppBoxRenderView::destroyWrtCore(WrtCorePtr wrt) +{ + LogD("enter"); + + if (wrt) { + wrt->Hide(); + } +} + +void AppBoxRenderView::hideBox() +{ + LogD("enter"); + if (m_isTouchableBox) { + deleteTimer(&m_boxTouchTimer); + } + + if (m_boxRenderInfo) { + destroyBoxWrtCore(); + if (m_boxRenderInfo->window) { + evas_object_hide(m_boxRenderInfo->window); + } + } +} + +void AppBoxRenderView::pauseBox() +{ + LogD("enter"); +} + +void AppBoxRenderView::resumeBox() +{ + LogD("enter"); + if (!m_showed) { + RenderView::show(); + } +} + +void AppBoxRenderView::showPd(RenderInfoPtr pdRenderInfo, RenderInfoPtr boxRenderInfo) +{ + LogD("enter"); + + std::string pdStartUrl = getStartUrl(URL_TYPE_PD, pdRenderInfo->defaultUrlParams); + if (m_pdFastOpen) { + destroyPdWrtCore(); + m_pdWrt = createWrtCore(URL_TYPE_PD, pdStartUrl, pdRenderInfo->window, m_ewkContext); + if (!m_pdWrt) { + LogD("no wrt core instance"); + return; + } + m_pdHelper = AppBoxPdHelper::create(pdRenderInfo->window); + + // resize webview fitted to width, height of pd + evas_object_resize( + m_pdWrt->GetCurrentWebview(), + pdRenderInfo->width, + pdRenderInfo->height); + // show pd + m_pdWrt->Show(); + m_pdHelper->finishOpen(m_pdWrt->GetCurrentWebview()); + } else { + m_pdHelper = PdHelper::create(pdRenderInfo, pdStartUrl); + } + + // show pd window + evas_object_show(pdRenderInfo->window); + + // need to create new snapshot when m_napshot is empty + if (!m_boxSnapshot) { + evas_object_show(getCurrentSnapShot()); + } + getPdBuffer()->setWebView(m_pdWrt->GetCurrentWebview()); + // show box + showBox(boxRenderInfo); + + // start timer for clearing existing snapshot in case of only pd open + addTimer(&m_boxRemoveSnapShotTimer, SNAPSHOT_REMOVE_TIME, removeBoxSnapShotTimerCallback); +} + +void AppBoxRenderView::hidePd() +{ + LogD("enter"); + + if (m_pdFastOpen) { + destroyPdWrtCore(); + } + m_pdHelper->close(); + m_pdHelper.reset(); + + // start timer for clearing existing snapshot in case of only pd open + struct stat tmp; + if (stat(WEB_PROVIDER_INSPECTOR_FILE_PATH, &tmp) == 0) { + addTimer(&m_boxRenderTimer, RENDER_MAX_TIME_FOR_INSPECTOR, fireBoxRenderTimerCallback); + } else { + addTimer(&m_boxRenderTimer, RENDER_MAX_TIME, fireBoxRenderTimerCallback); + } + +} + +void AppBoxRenderView::didBoxTouched(int x, int y) +{ + LogD("x : %d, y: %d", x, y); + if (!m_isTouchableBox) { + return; + } + + if (!m_boxWrt) { + LogD("no webview"); + return; + } + + // if needed, resume render view + if (m_boxRenderTimer) { + deleteTimer(&m_boxRenderTimer); + } else { + if (!m_boxTouchTimer) { + m_boxRenderBuffer->startCanvasUpdate(); + + // temp condition + if (m_boxWrt_isSuspended == true) + { + m_boxWrt_isSuspended = false; + m_boxWrt->Resume(); + } + } else { + deleteTimer(&m_boxTouchTimer); + } + } + addTimer(&m_boxTouchTimer, TOUCH_MAX_WAIT_TIME, fireBoxTouchTimerCallback); +} + +void AppBoxRenderView::didPdTouched(int x, int y) +{ + LogD("x : %d, y: %d", x, y); +} + +Evas_Object* AppBoxRenderView::getBoxWebView() +{ + if (!m_pdHelper) { + return m_boxWrt->GetCurrentWebview(); + } else { + // Here, we can't use GetCurrentWebView() of wrt-core to get Box' webview, + // because in the non fast-open, GetCurrentWebview() returns PD's webview. + return m_pdHelper->getBoxWebView(); + } +} + +Evas_Object* AppBoxRenderView::getPdWebView() +{ + if (!m_pdHelper) { + return NULL; + } + + return m_pdHelper->getPdWebView(); +} + +std::string AppBoxRenderView::getAppId(std::string& boxId) +{ + LogD("enter"); + + const char* appId = web_provider_livebox_get_app_id(boxId.c_str()); + if (!appId) { + LogD("no appid of %s", boxId.c_str()); + return std::string(); + } + + return std::string(appId); +} + +std::string AppBoxRenderView::getStartUrl(UrlType type, std::string& defaultParams) +{ + const char* path = NULL; + switch (type) { + case URL_TYPE_BOX: + path = livebox_service_lb_script_path(m_boxId.c_str()); + break; + case URL_TYPE_PD: + path = livebox_service_pd_script_path(m_boxId.c_str()); + break; + default: + LogD("no available type"); + } + + std::string startUrl; + if (path) { + LogD("path : %s", path); + startUrl = path; + } else { + // TODO In this case, fallback page will be loaded. + LogE("Fail to get service lib script path"); + } + + // add default parameters to start url + startUrl += defaultParams; + + return startUrl; +} + +Evas_Object* AppBoxRenderView::getCurrentSnapShot() +{ + LogD("enter"); + + clearSnapShot(); + m_boxSnapshot = m_boxRenderBuffer->getSnapshot(); + + return m_boxSnapshot; +} + +void AppBoxRenderView::clearSnapShot() +{ + LogD("enter"); + if (m_boxSnapshot) { + evas_object_del(m_boxSnapshot); + m_boxSnapshot = NULL; + } +} + +void AppBoxRenderView::showSnapShot() +{ + LogD("enter"); + if (m_boxSnapshot) { + evas_object_raise(m_boxSnapshot); + evas_object_show(m_boxSnapshot); + } +} + +void AppBoxRenderView::hideSnapShot() +{ + LogD("enter"); + if (m_boxSnapshot) { + evas_object_hide(m_boxSnapshot); + evas_object_lower(m_boxSnapshot); + } +} + +void AppBoxRenderView::addTimer(Ecore_Timer** timer, double interval, Ecore_Task_Cb callback) +{ + LogD("enter"); + if (*timer) { + deleteTimer(timer); + } + + *timer = ecore_timer_add(interval, callback, this); +} + +void AppBoxRenderView::deleteTimer(Ecore_Timer** timer) +{ + LogD("enter"); + if (*timer) { + ecore_timer_del(*timer); + *timer = NULL; + } +} + +void AppBoxRenderView::stopRenderBox() +{ + deleteTimer(&m_boxRenderTimer); + m_boxRenderBuffer->stopCanvasUpdate(); + if (m_isTouchableBox) { + // stop touch timer + deleteTimer(&m_boxTouchTimer); + + // temp condition + if (m_boxWrt_isSuspended == false) + { + m_boxWrt_isSuspended = true; + m_boxWrt->Suspend(); + } + } else { + // Before webview should be removed, + // new evas object with last render data should be created + // otherwise, after webview is removed, box is white screen. + evas_object_show(getCurrentSnapShot()); + destroyBoxWrtCore(); + } +} + +void AppBoxRenderView::setWebViewBasicSetting(Evas_Object* webview) +{ + LogD("enter"); + + if (!webview) { + return; + } + Ewk_Settings* setting = ewk_view_settings_get(webview); + // disable shadow effect on scrolling +#if !ENABLE(WEBKIT_UPVERSION) + ewk_settings_edge_effect_enabled_set(setting, EINA_FALSE); + // Disable ime features + ewk_settings_default_keypad_enabled_set(setting, EINA_FALSE); +#endif + // To support transparent background + ewk_view_bg_color_set(webview, 0, 0, 0, 1); + ewk_view_visibility_set(webview, EINA_TRUE); + + // To know starting point for updating buffer + evas_object_smart_callback_add( + webview, + "load,nonemptylayout,finished", + loadNonEmptyLayoutFinishedCallback, + this); + evas_object_smart_callback_add( + webview, + "frame,rendered", + frameRenderedCallback, + this); + // To set font type whenever font changed + ewk_view_use_settings_font(webview); +} + +void AppBoxRenderView::consoleMessage(int level, const char* format, ...) +{ + va_list args; + va_start(args, format); + switch (level) { + case DLOG_DEBUG: + ALOG_VA(LOG_DEBUG, consoleMessageLogTag.c_str(), format, args); + break; + case DLOG_WARN: + ALOG_VA(LOG_WARN, consoleMessageLogTag.c_str(), format, args); + break; + case DLOG_ERROR: + ALOG_VA(LOG_ERROR, consoleMessageLogTag.c_str(), format, args); + break; + default: + ALOG_VA(LOG_DEBUG, consoleMessageLogTag.c_str(), format, args); + break; + } + va_end(args); +} + +Eina_Bool AppBoxRenderView::fireBoxRenderTimerCallback(void* data) +{ + LogD("enter"); + + AppBoxRenderView* This = static_cast<AppBoxRenderView*>(data); + This->m_boxRenderTimer = NULL; + This->stopRenderBox(); + + return ECORE_CALLBACK_CANCEL; +} + +Eina_Bool AppBoxRenderView::fireBoxTouchTimerCallback(void* data) +{ + + LogD("enter"); + AppBoxRenderView* This = static_cast<AppBoxRenderView*>(data); + This->m_boxRenderBuffer->stopCanvasUpdate(); + + // temp condition + if (This->m_boxWrt_isSuspended == false) + { + This->m_boxWrt_isSuspended = true; + This->m_boxWrt->Suspend(); + } + + This->m_boxTouchTimer = NULL; + + return ECORE_CALLBACK_CANCEL; +} + + +Eina_Bool AppBoxRenderView::removeBoxSnapShotTimerCallback(void* data) +{ + LogD("enter"); + + AppBoxRenderView* This = static_cast<AppBoxRenderView*>(data); + if (!(This->m_boxFinishLoad && This->m_boxFrameRendered)) { + return ECORE_CALLBACK_RENEW; + } + + if (!This->m_boxWaitFrameRender) { + This->m_boxWaitFrameRender = true; + return ECORE_CALLBACK_RENEW; + } + // hide snapshot because valid frame has been prepared generally. + This->clearSnapShot(); + This->m_boxRenderBuffer->startCanvasUpdate(); + + if (This->m_showIcon) { + evas_object_del(This->m_boxIcon); + This->m_showIcon = false; + } + + // move to inside of viewport to prevent overlap with snapshot image + evas_object_move(This->m_boxWrt->GetCurrentWebview(), 0, 0); + evas_object_show(This->m_boxWrt->GetCurrentWebview()); + + This->m_boxRemoveSnapShotTimer = NULL; + return ECORE_CALLBACK_CANCEL; +} + +Eina_Bool AppBoxRenderView::openPdIdlerCallback(void* data) +{ + LogD("enter"); + AppBoxRenderView* This = static_cast<AppBoxRenderView*>(data); + if (This && This->m_pdHelper) { + This->m_pdHelper->startOpen(); + } + return ECORE_CALLBACK_CANCEL; +} + +void AppBoxRenderView::executeScriptCallback( + Evas_Object* webview, const char* result, void* data) +{ + LogD("enter"); + UNUSED_PARAM(webview); + UNUSED_PARAM(data); + + std::string resultStr(result ? result : "null"); + LogD("result: %s", resultStr.c_str()); +} + +void AppBoxRenderView::startLoadCallback(Evas_Object* webview, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(eventInfo); + if(!webview) { + return; + } + // execute injection for creating js objects + std::ifstream jsFile(injectionFile); + std::string jsString((std::istreambuf_iterator<char>(jsFile)), + std::istreambuf_iterator<char>()); + + std::ostringstream script; + script << jsString; + + // add javascripts for operation of synchronous call + script << jsRegisterBoxInfoFunction << "('box-id', '" << m_boxId << "');"; + script << jsRegisterBoxInfoFunction << "('instance-id', '" << m_contentInfo << "');"; + + //LogD("injected js code: %s", script.str().c_str()); + ewk_view_script_execute(webview, script.str().c_str(), executeScriptCallback, this); +} + +void AppBoxRenderView::finishBoxLoadCallback(Evas_Object* webview, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(eventInfo); + if (!webview) { + return; + } + + ewk_view_visibility_set(webview, EINA_TRUE); + + if (!m_pdHelper) { + // start render timer + struct stat tmp; + if (stat(WEB_PROVIDER_INSPECTOR_FILE_PATH, &tmp) == 0) { + addTimer(&m_boxRenderTimer, RENDER_MAX_TIME_FOR_INSPECTOR, fireBoxRenderTimerCallback); + } else { + addTimer(&m_boxRenderTimer, RENDER_MAX_TIME, fireBoxRenderTimerCallback); + } + } else { + if (!m_pdFastOpen) { + if (!(m_pdHelper->isPdOpened()) && + webview == m_pdHelper->getBoxWebView()) + { + // open pd + ecore_idler_add(openPdIdlerCallback, this); + } + } + } + + // set flag + m_boxFinishLoad = true; +} + +void AppBoxRenderView::finishPdLoadCallback(Evas_Object* webview, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(eventInfo); + if (!webview) { + return; + } + + ewk_view_visibility_set(webview, EINA_TRUE); +} + +void AppBoxRenderView::createWindowBeforeCallback(Evas** canvas, Evas_Object* parent) +{ + LogD("enter"); + + if (m_pdHelper) { + if (!(m_pdHelper->isPdOpened()) && + parent == m_pdHelper->getBoxWebView()) + { + LogD("pd canvas is used"); + *canvas = m_pdHelper->getPdCanvas(); + return; + } + } + + LogD("canvas of this webview is used"); + *canvas = evas_object_evas_get(parent); +} + +void AppBoxRenderView::createWindowAfterCallback(Evas_Object* parent, Evas_Object* child) +{ + LogD("enter"); + if (!parent) { + return; + } + + if (m_pdHelper) { + Evas* parentCanvas = evas_object_evas_get(parent); + Evas* childCanvas = evas_object_evas_get(child); + + if (parentCanvas != childCanvas) { + // wrt-core change visibility value to false internally + // So plugin should reset this value to true for painting parent webview + ewk_view_visibility_set(parent, EINA_TRUE); + evas_object_show(parent); + m_pdHelper->finishOpen(child); + } + } + + setWebViewBasicSetting(child); + evas_object_show(child); +} + +void AppBoxRenderView::setBufferCallback(Evas_Object* webview) +{ + LogD("enter"); + evas_object_show(webview); + evas_object_focus_set(webview, EINA_TRUE); +} + +void AppBoxRenderView::unsetBufferCallback(Evas_Object* webview) +{ + LogD("enter"); + evas_object_hide(webview); +} + +void AppBoxRenderView::decideNavigationCallback(Evas_Object* webview, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(webview); + + Ewk_Policy_Decision* policyDecision = static_cast<Ewk_Policy_Decision*>(eventInfo); + const char* url = ewk_policy_decision_url_get(policyDecision); + if (!url || !*url) { + LogE("url is empty"); + return; + } + std::string uri(url); + + // navigation of box scheme should be ignored + processBoxScheme(uri); +} + +void AppBoxRenderView::crashWebProcessCallback(Evas_Object* webview, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(webview); + UNUSED_PARAM(eventInfo); + LogD("instanceId: %s", m_instanceId.c_str()); + elm_exit(); +} + +void AppBoxRenderView::loadNonEmptyLayoutFinishedCallback( + void* data, Evas_Object* webview, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(data); + UNUSED_PARAM(webview); + UNUSED_PARAM(eventInfo); +} + +void AppBoxRenderView::frameRenderedCallback( + void* data, Evas_Object* webview, void* eventInfo) +{ + LogD("enter"); + UNUSED_PARAM(webview); + UNUSED_PARAM(eventInfo); + + // start to update render buffer! + AppBoxRenderView* This = static_cast<AppBoxRenderView*>(data); + + // set flag + This->m_boxFrameRendered = true; + + // move to inside of viewport to prevent overlap with snapshot image + if (!This->m_boxRemoveSnapShotTimer) { + evas_object_move(This->m_boxWrt->GetCurrentWebview(), 0, 0); + } +} + +void AppBoxRenderView::consoleMessageCallback(Evas_Object* webview, void* eventInfo) +{ + UNUSED_PARAM(webview); + + Ewk_Console_Message* consoleMessage = static_cast<Ewk_Console_Message*>(eventInfo); + + std::stringstream buf; + unsigned int lineNumber = ewk_console_message_line_get(consoleMessage); + const char* text = ewk_console_message_text_get(consoleMessage); + const char* source = ewk_console_message_source_get(consoleMessage); + if (lineNumber) { + buf << source << ":"; + buf << lineNumber << ":"; + } + buf << text; + + int level; + switch (ewk_console_message_level_get(consoleMessage)) { + case EWK_CONSOLE_MESSAGE_LEVEL_TIP: + case EWK_CONSOLE_MESSAGE_LEVEL_LOG: + case EWK_CONSOLE_MESSAGE_LEVEL_DEBUG: + level = DLOG_DEBUG; + break; + case EWK_CONSOLE_MESSAGE_LEVEL_WARNING: + level = DLOG_WARN; + break; + case EWK_CONSOLE_MESSAGE_LEVEL_ERROR: + level = DLOG_ERROR; + break; + default: + level = DLOG_DEBUG; + break; + } + AppBoxRenderView::consoleMessage(level, "%s", buf.str().c_str()); +} + + +void AppBoxRenderView::showIcon(char *iconString, int width, int height) +{ + LogD("enter"); + + Evas_Load_Error err; + Evas_Object *snapshot; + int w,h; + int x = 0; + int y = 0; + + if (!iconString) { + LogE("iconString is NULL"); + return; + } + + snapshot = evas_object_image_add(m_boxRenderBuffer->getCanvas()); + if (!snapshot) { + LogE("evas_object_image_add FAILED"); + return; + } + + const char *string = const_cast<const char *>(iconString); + evas_object_image_colorspace_set(snapshot, EVAS_COLORSPACE_ARGB8888); + evas_object_image_alpha_set(snapshot, EINA_TRUE); + evas_object_image_file_set(snapshot, string, NULL); + err = evas_object_image_load_error_get(snapshot); + if (err != EVAS_LOAD_ERROR_NONE) { + LogE("Load error: %s\n", evas_load_error_str(err)); + evas_object_del(snapshot); + return; + } + evas_object_image_size_get(snapshot, &w, &h); + evas_object_image_filled_set(snapshot, EINA_TRUE); + + + if (width > w) { + x = (width - w) >> 1; + } + + if (height > h) { + y = (height - h) >> 1; + } + + evas_object_image_fill_set(snapshot, 0, 0, w, h); + evas_object_move(snapshot, x, y); + evas_object_show(snapshot); + evas_object_resize(snapshot, w, h); + + provider_send_updated( + m_boxId.c_str(), + m_instanceId.c_str(), + width, height, + 0, m_contentInfo.c_str(), NULL); + + m_boxIcon = snapshot; + m_showIcon = true; +} diff --git a/src_wearable/Plugin/AppBoxPlugin/AppBoxRenderView.h b/src_wearable/Plugin/AppBoxPlugin/AppBoxRenderView.h new file mode 100755 index 0000000..0812d0e --- /dev/null +++ b/src_wearable/Plugin/AppBoxPlugin/AppBoxRenderView.h @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file AppBoxRenderView.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef APP_BOX_RENDER_VIEW_H +#define APP_BOX_RENDER_VIEW_H + +#include <string> +#include <memory> +#include <Eina.h> +#include <Ecore.h> +#include <Evas.h> +#include <ewk_context.h> +#include <i_runnable_widget_object.h> +#include <Core/BoxData.h> +#include <Core/View/IPdHelper.h> +#include <Core/View/RenderView.h> + +class AppBoxRenderBuffer; + +class AppBoxRenderView: public RenderView { + public: + typedef std::shared_ptr<Ewk_Context> EwkContextPtr; + + static IRenderViewPtr create(BoxInfoPtr boxInfo, EwkContextPtr ewkContext) + { + return IRenderViewPtr(new AppBoxRenderView(boxInfo, ewkContext)); + }; + virtual void showBox(RenderInfoPtr boxRenderInfo); + virtual void hideBox(); + virtual void pauseBox(); + virtual void resumeBox(); + virtual void showPd(RenderInfoPtr pdRenderInfo, RenderInfoPtr boxRenderInfo); + virtual void hidePd(); + virtual void didBoxTouched(int x, int y); + virtual void didPdTouched(int x, int y); + virtual ~AppBoxRenderView(); + + private: + // type definition + typedef std::shared_ptr<WRT::IRunnableWidgetObject> WrtCorePtr; + enum UrlType { + URL_TYPE_BOX, + URL_TYPE_PD + }; + + WrtCorePtr createWrtCore( + UrlType type, std::string& startUrl, + Evas_Object* win, EwkContextPtr ewkContext); + void setWebViewBasicSetting(Evas_Object* webview); + void destroyWrtCore(WrtCorePtr wrt); + void destroyBoxWrtCore(); + void destroyPdWrtCore(); + Evas_Object* getBoxWebView(); + Evas_Object* getPdWebView(); + std::string getAppId(std::string& boxId); + std::string getStartUrl(UrlType type, std::string& defaultParams); + Evas_Object* getCurrentSnapShot(); + void clearSnapShot(); + void showSnapShot(); + void hideSnapShot(); + void addTimer(Ecore_Timer** timer, double interval, Ecore_Task_Cb callback); + void deleteTimer(Ecore_Timer** timer); + void stopRenderBox(); + void consoleMessage(int level, const char* format, ...); + void showIcon(char *iconString, int width, int height); + + // timer and idler callback + static Eina_Bool fireBoxRenderTimerCallback(void* data); + static Eina_Bool fireBoxTouchTimerCallback(void* data); + static Eina_Bool removeBoxSnapShotTimerCallback(void* data); + static Eina_Bool openPdIdlerCallback(void* data); + + // ewk view callback + static void executeScriptCallback( + Evas_Object* webview, const char* result, void* data); + static void loadNonEmptyLayoutFinishedCallback( + void* data, Evas_Object* webview, void* eventInfo); + static void frameRenderedCallback( + void* data, Evas_Object* webview, void* eventInfo); + + // user Callbacks of RunnableWidgetObject + void startLoadCallback(Evas_Object* webview, void* eventInfo); + void finishBoxLoadCallback(Evas_Object* webview, void* eventInfo); + void finishPdLoadCallback(Evas_Object* webview, void* eventInfo); + void createWindowBeforeCallback(Evas** canvas, Evas_Object* parent); + void createWindowAfterCallback(Evas_Object* parent, Evas_Object* child); + void setBufferCallback(Evas_Object* webview); + void unsetBufferCallback(Evas_Object* webview); + void decideNavigationCallback(Evas_Object* webview, void* eventInfo); + void crashWebProcessCallback(Evas_Object* webview, void* eventInfo); + void consoleMessageCallback(Evas_Object* webview, void* eventInfo); + + // constructor + explicit AppBoxRenderView(BoxInfoPtr boxInfo, EwkContextPtr ewkContext); + + // members + std::string m_appId; + std::string m_boxId; + std::string m_instanceId; + std::string m_contentInfo; + EwkContextPtr m_ewkContext; + RenderInfoPtr m_boxRenderInfo; + WrtCorePtr m_boxWrt; + WrtCorePtr m_pdWrt; + IRenderBufferPtr m_boxRenderBuffer; + IRenderBufferPtr m_pdRenderBuffer; + Evas_Object* m_boxSnapshot; + Ecore_Timer* m_boxRenderTimer; + Ecore_Timer* m_boxTouchTimer; + Ecore_Timer* m_boxRemoveSnapShotTimer; + IPdHelperPtr m_pdHelper; + Evas_Object* m_boxIcon; + + // for check status of webview + bool m_pdFastOpen; + bool m_boxFinishLoad; + bool m_boxFrameRendered; + bool m_boxWaitFrameRender; + bool m_isTouchableBox; + + // TODO this temporary flag should removed! + bool m_boxWrt_isSuspended; + bool m_showed; + bool m_showIcon; +}; + +#endif // APP_BOX_RENDER_VIEW_H diff --git a/src_wearable/Plugin/AppBoxPlugin/CMakeLists.txt b/src_wearable/Plugin/AppBoxPlugin/CMakeLists.txt new file mode 100644 index 0000000..df14513 --- /dev/null +++ b/src_wearable/Plugin/AppBoxPlugin/CMakeLists.txt @@ -0,0 +1,73 @@ +# Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved +# +# Licensed under the Flora License, Version 1.1 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://floralicense.org/license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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) + +SET(TARGET_NAME web-provider-plugin-app) +SET(DEPS ${TARGET_NAME}_DEPS) + +PKG_CHECK_MODULES(${DEPS} + ail + ewebkit2 + wrt-core + dpl-efl + evas + ecore + eina + livebox-service + dlog + provider # this should be removed + REQUIRED +) +ADD_DEFINITIONS(${${DEPS}_CFLAGS}) + +SET(SRCS + ${CMAKE_CURRENT_SOURCE_DIR}/box_plugin_interface.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/AppBoxManager.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/AppBoxPluginFactory.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/AppBoxRenderView.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/AppBoxPdHelper.cpp +) + +SET(HEADERS + ${${DEPS}_INCLUDE_DIRS} + ${CMAKE_CURRENT_SOURCE_DIR} +) +INCLUDE_DIRECTORIES(${HEADERS}) + +ADD_LIBRARY(${TARGET_NAME} SHARED ${SRCS}) + +SET_TARGET_PROPERTIES(${TARGET_NAME} PROPERTIES + COMPILE_FLAGS -fPIC + LINK_FLAGS "-Wl,--as-needed -Wl,--hash-style=both" +) + +SET_TARGET_PROPERTIES(${TARGET_NAME} + PROPERTIES + SOVERSION ${CMAKE_PROJECT_API_VERSION} + VERSION ${CMAKE_PROJECT_VERSION} +) + +TARGET_LINK_LIBRARIES(${TARGET_NAME} + ${${DEPS}_LIBRARIES} + ${TARGET_CORE} +) + +INSTALL(TARGETS ${TARGET_NAME} + DESTINATION lib/${PROJECT_NAME} + PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE + GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE +) + +INSTALL_FILE(app.json lib/${PROJECT_NAME}) diff --git a/src_wearable/Plugin/AppBoxPlugin/app.json b/src_wearable/Plugin/AppBoxPlugin/app.json new file mode 100644 index 0000000..6388702 --- /dev/null +++ b/src_wearable/Plugin/AppBoxPlugin/app.json @@ -0,0 +1,5 @@ +{ + "type" : "app", + "path" : "/usr/lib/web-provider/libweb-provider-plugin-app.so", + "supported_size" : ["1x1","2x1","2x2"] +} diff --git a/src_wearable/Plugin/AppBoxPlugin/box_plugin_interface.cpp b/src_wearable/Plugin/AppBoxPlugin/box_plugin_interface.cpp new file mode 100644 index 0000000..ca5e65e --- /dev/null +++ b/src_wearable/Plugin/AppBoxPlugin/box_plugin_interface.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file box_plugin_interface.cpp + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#include <memory> +#include <Core/BoxData.h> +#include <Core/Util/Log.h> +#include <Plugin/box_plugin_interface.h> +#include "AppBoxManager.h" +#include "AppBoxPluginFactory.h" + +static std::shared_ptr<IBoxManager> g_manager; + +int web_provider_plugin_interface_initialize() +{ + LogD("enter"); + IBoxPluginFactoryPtr factory(new AppBoxPluginFactory()); + g_manager = AppBoxManager::create(factory); + + return 0; +} + +int web_provider_plugin_interface_command(const request_cmd_type type, const BoxInfoPtr& boxInfo) +{ + LogD("enter"); + int ret = g_manager->doCommand(type, boxInfo); + + if (!ret) { + return -1; + } + + return 0; +} + +int web_provider_plugin_interface_shutdown() +{ + LogD("enter"); + g_manager.reset(); + return 0; +} diff --git a/src_wearable/Plugin/BoxPluginConnector.cpp b/src_wearable/Plugin/BoxPluginConnector.cpp new file mode 100755 index 0000000..d50bc1b --- /dev/null +++ b/src_wearable/Plugin/BoxPluginConnector.cpp @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file BoxPluginConnector.cpp + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#include <map> +#include <dlfcn.h> +#include <Core/Util/Log.h> +#include <Core/BoxData.h> +#include <API/web_provider_plugin_info.h> +#include "box_plugin_interface.h" +#include "BoxPluginConnector.h" + +BoxPluginConnector::BoxPluginConnector() +{ +} + +BoxPluginConnector::~BoxPluginConnector() +{ +} + +bool BoxPluginConnector::initialize() +{ + LogD("enter"); + + int count; + web_provider_plugin_info** pluginList = NULL; + pluginList = web_provider_plugin_get_installed_list(&count); + + if (!pluginList) { + LogD("failed to get installed plugin's information"); + return false; + } + + if (count <= 0) { + LogD("There is no available livebox plugins"); + return false; + } + + m_pluginMap.clear(); + + // get information of installed plugin + LogD("get information of installed plugin"); + for (int i = 0; i < count; i++) { + if (!pluginList[i]) { + continue; + } + + LogD("plugin path: %s", pluginList[i]->path); + void* handle = dlopen(pluginList[i]->path, RTLD_LAZY); + if (!handle) { + LogD("failed to load plugin so: %s", dlerror()); + continue; + } + + std::shared_ptr<plugin_interfaces> pluginInfo(new plugin_interfaces); + + pluginInfo->handle = handle; + pluginInfo->service_boxid = NULL; + if (pluginList[i]->service_boxid) { + pluginInfo->service_boxid = strdup(pluginList[i]->service_boxid); + } + + pluginInfo->initialize = + reinterpret_cast<plugin_interface_func_initialize>( + dlsym(handle, WEB_PROVIDER_PLUGIN_INTERFACE_SYM_INITIALIZE)); + pluginInfo->command = + reinterpret_cast<plugin_interface_func_command>( + dlsym(handle, WEB_PROVIDER_PLUGIN_INTERFACE_SYM_COMMAND)); + pluginInfo->shutdown = + reinterpret_cast<plugin_interface_func_shutdown>( + dlsym(handle, WEB_PROVIDER_PLUGIN_INTERFACE_SYM_SHUTDOWN)); + + if (!pluginInfo->initialize || !pluginInfo->command || + !pluginInfo->shutdown) + { + LogD("symbol for plugin interface is not found"); + continue; + } + + m_pluginMap[std::string(pluginList[i]->type)] = pluginInfo; + } + + // initialize plugins + for (auto it = m_pluginMap.begin(); + it != m_pluginMap.end(); ++it) + { + if (it->second) { + // TODO add exception or abnormal action on loading plugin + if (it->second->initialize() < 0) { + LogD("fail to intialize plugin"); + continue; + } + } + } + + // release information + LogD("release json data of plugins"); + web_provider_plugin_release_installed_list(pluginList, count); + + return true; +} + +bool BoxPluginConnector::shutdown() +{ + LogD("enter"); + // if needed, unload each plugin's DSO. + for (auto it = m_pluginMap.begin(); + it != m_pluginMap.end(); ++it) + { + if (it->second) { + it->second->shutdown(); + dlclose(it->second->handle); + } + } + + return true; +} + +bool BoxPluginConnector::requestCommand( + const request_cmd_type type, const BoxInfoPtr& boxInfo) +{ + LogD("enter"); + + // in case of request of resume all or pause all, all plugins should handle that. + if (type == REQUEST_CMD_RESUME_ALL || + type == REQUEST_CMD_PAUSE_ALL || + type == REQUEST_CMD_UPDATE_ALL || + type == REQUEST_CMD_UPDATE_APPBOX) { + for (auto it = m_pluginMap.begin(); + it != m_pluginMap.end(); ++it) + { + if (it->second) { + it->second->command(type, boxInfo); + } + } + return true; + } + + const std::shared_ptr<plugin_interfaces> plugin = m_pluginMap[boxInfo->boxType]; + if (!plugin) { + LogD("not available livebox type"); + return false; + } + + int ret = plugin->command(type, boxInfo); + if (ret < 0) { + LogD("failed to request command"); + return false; + } + + return true; +} + +std::string BoxPluginConnector::getBoxType(const std::string& serviceBoxId) +{ + LogD("enter"); + + std::string type; + for (auto it = m_pluginMap.begin(); + it != m_pluginMap.end(); ++it) + { + if (it->second && it->second->service_boxid) { + if (serviceBoxId == it->second->service_boxid) { + LogD("service box id is matched!: %s", it->first.c_str()); + type = it->first; + break; + } + } + } + + return type; +} diff --git a/src_wearable/Plugin/BoxPluginConnector.h b/src_wearable/Plugin/BoxPluginConnector.h new file mode 100644 index 0000000..5ada8db --- /dev/null +++ b/src_wearable/Plugin/BoxPluginConnector.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file BoxPluginConnector.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef BOX_PLUGIN_CONNECTOR_H +#define BOX_PLUGIN_CONNECTOR_H + +#include <map> +#include <Core/BoxData.h> +#include "IBoxPluginConnector.h" +#include "box_plugin_interface.h" + +class BoxPluginConnector: public IBoxPluginConnector { + public: // IBoxPluginConnector + static IBoxPluginConnectorPtr create() + { + return IBoxPluginConnectorPtr(new BoxPluginConnector()); + }; + virtual bool initialize(); + virtual bool shutdown(); + virtual bool requestCommand( + const request_cmd_type type, const BoxInfoPtr& boxInfo); + virtual std::string getBoxType(const std::string& serviceBoxId); + virtual ~BoxPluginConnector(); + + private: + BoxPluginConnector(); + + // type definition + typedef std::map<std::string, std::shared_ptr<plugin_interfaces> > pluginMap; + + pluginMap m_pluginMap; + +}; + +#endif // BOX_PLUGIN_CONNECTOR_H diff --git a/src_wearable/Plugin/CMakeLists.txt b/src_wearable/Plugin/CMakeLists.txt new file mode 100644 index 0000000..349ddb0 --- /dev/null +++ b/src_wearable/Plugin/CMakeLists.txt @@ -0,0 +1,67 @@ +# Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved +# +# Licensed under the Flora License, Version 1.1 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://floralicense.org/license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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) + +SET(TARGET_NAME ${TARGET_PLUGIN}) +SET(DEPS ${TARGET_NAME}_DEPS) + +PKG_CHECK_MODULES(${DEPS} + evas + ewebkit2 + dlog + REQUIRED +) +ADD_DEFINITIONS(${${DEPS}_CFLAGS}) + +SET(SRCS + ${CMAKE_CURRENT_SOURCE_DIR}/BoxPluginConnector.cpp +) + +SET(HEADERS + ${${DEPS}_INCLUDE_DIRS} + ${CMAKE_CURRENT_SOURCE_DIR} +) +INCLUDE_DIRECTORIES(${HEADERS}) + +ADD_LIBRARY(${TARGET_NAME} STATIC ${SRCS}) + +SET_TARGET_PROPERTIES(${TARGET_NAME} PROPERTIES + COMPILE_FLAGS -fPIC + LINK_FLAGS "-Wl,--as-needed -Wl,--hash-style=both" +) + +SET_TARGET_PROPERTIES(${TARGET_NAME} + PROPERTIES + SOVERSION ${CMAKE_PROJECT_API_VERSION} + VERSION ${CMAKE_PROJECT_VERSION} +) + +TARGET_LINK_LIBRARIES(${TARGET_NAME} + ${${DEPS}_LDFLAGS} "-ldl" + ${${DEPS}_LIBRARIES} +) + +INSTALL(TARGETS ${TARGET_NAME} + DESTINATION lib + PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE + GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE +) + +GET_FILENAME_COMPONENT(CURRENT_DIR_NAME ${CMAKE_CURRENT_SOURCE_DIR} NAME) +INSTALL_FILE(IBoxPluginFactory.h include/${PROJECT_NAME}/${CURRENT_DIR_NAME}) +INSTALL_FILE(box_plugin_interface.h include/${PROJECT_NAME}/${CURRENT_DIR_NAME}) + +# openable plugins of web livebox +ADD_SUBDIRECTORY(AppBoxPlugin) diff --git a/src_wearable/Plugin/IBoxPluginConnector.h b/src_wearable/Plugin/IBoxPluginConnector.h new file mode 100644 index 0000000..3e94fb8 --- /dev/null +++ b/src_wearable/Plugin/IBoxPluginConnector.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file IBoxPluginConnector.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef I_BOX_PLUGIN_CONNECTOR_H +#define I_BOX_PLUGIN_CONNECTOR_H + +#include <memory> +#include <Core/BoxData.h> +#include <Core/Util/Noncopyable.h> +#include "box_plugin_interface.h" + +class IBoxPluginConnector: Noncopyable { + public: + virtual bool initialize() = 0; + virtual bool shutdown() = 0; + virtual bool requestCommand( + const request_cmd_type type, const BoxInfoPtr& boxInfo) = 0; + virtual std::string getBoxType(const std::string& serviceBoxId) = 0; + virtual ~IBoxPluginConnector() {}; +}; + +typedef std::shared_ptr<IBoxPluginConnector> IBoxPluginConnectorPtr; + +#endif // I_BOX_PLUGIN_CONNECTOR_H diff --git a/src_wearable/Plugin/IBoxPluginFactory.h b/src_wearable/Plugin/IBoxPluginFactory.h new file mode 100644 index 0000000..e0ff5ba --- /dev/null +++ b/src_wearable/Plugin/IBoxPluginFactory.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file IBoxPluginFactory.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef I_BOX_PLUGIN_FACTORY_H +#define I_BOX_PLUGIN_FACTORY_H + +#include <string> +#include <memory> +#include <Evas.h> +#include <ewk_context.h> + +// forward declaration +class IRenderView; +struct BoxInfo; + +class IBoxPluginFactory { + public: + virtual std::shared_ptr<IRenderView> createRenderView( + std::shared_ptr<BoxInfo> boxInfo, + std::shared_ptr<Ewk_Context> ewkContext) = 0; + virtual ~IBoxPluginFactory() {}; +}; + +typedef std::shared_ptr<IBoxPluginFactory> IBoxPluginFactoryPtr; + +#endif //I_BOX_PLUGIN_FACTORY_H diff --git a/src_wearable/Plugin/box_plugin_interface.h b/src_wearable/Plugin/box_plugin_interface.h new file mode 100755 index 0000000..28ef571 --- /dev/null +++ b/src_wearable/Plugin/box_plugin_interface.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file box_plugin_interface.h + * @author Yunchan Cho (yunchan.cho@samsung.com) + */ +#ifndef BOX_PLUGIN_INTERFACE_H +#define BOX_PLUGIN_INTERFACE_H + +#include <string> +#include <Core/BoxData.h> + +#ifndef EXPORT_API +#define EXPORT_API __attribute__((visibility("default"))) +#endif + +#define WEB_PROVIDER_PLUGIN_INTERFACE_SYM_INITIALIZE "web_provider_plugin_interface_initialize" +#define WEB_PROVIDER_PLUGIN_INTERFACE_SYM_COMMAND "web_provider_plugin_interface_command" +#define WEB_PROVIDER_PLUGIN_INTERFACE_SYM_SHUTDOWN "web_provider_plugin_interface_shutdown" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + REQUEST_CMD_ADD_BOX, + REQUEST_CMD_REMOVE_BOX, + REQUEST_CMD_OPEN_PD, + REQUEST_CMD_CLOSE_PD, + REQUEST_CMD_RESIZE_BOX, + REQUEST_CMD_RESUME_BOX, + REQUEST_CMD_PAUSE_BOX, + REQUEST_CMD_RESUME_ALL, + REQUEST_CMD_PAUSE_ALL, + REQUEST_CMD_CHANGE_PERIOD, + REQUEST_CMD_UPDATE_BOX, + REQUEST_CMD_UPDATE_ALL, + REQUEST_CMD_UPDATE_APPBOX +} request_cmd_type; + +// definition of interface function type +typedef int (*plugin_interface_func_initialize)(void); +typedef int (*plugin_interface_func_command)( + const request_cmd_type type, const BoxInfoPtr& boxInfo); +typedef int (*plugin_interface_func_shutdown)(void); + +typedef struct { + void* handle; + const char* service_boxid; + plugin_interface_func_initialize initialize; + plugin_interface_func_command command; + plugin_interface_func_shutdown shutdown; +} plugin_interfaces; + +// inteface functions that should be implemented by each plugin +EXPORT_API int web_provider_plugin_interface_initialize(); +EXPORT_API int web_provider_plugin_interface_command( + const request_cmd_type type, const BoxInfoPtr& boxInfo); +EXPORT_API int web_provider_plugin_interface_shutdown(); + +#ifdef __cplusplus +} +#endif + +#endif // BOX_PLUGIN_INTERFACE_H 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..c370f4a --- /dev/null +++ b/uncrustify.sh @@ -0,0 +1 @@ +uncrustify -c uncrustify.cfg --no-backup `find . -regex "\(.*\.cpp\|.*\.h\|.*\.c\|.*\.cc\)"` |