From e5039791a403d48b5e6db065b97fcef3833c807f Mon Sep 17 00:00:00 2001 From: wanghuajian Date: Mon, 25 Mar 2024 12:46:05 +0800 Subject: [PATCH] add pasteboard Signed-off-by: wanghuajian --- CMakeLists.txt | 3 +- mock/CMakeLists.txt | 2 + mock/include/CMakeLists.txt | 5 +- .../ability_base/base/include/int_wrapper.h | 1 + .../include/ability_manager_client.h | 20 +- .../napi_common/in_process_call_wrapper.h | 36 + .../include/bundlemgr/bundle_mgr_interface.h | 6 +- .../ipc/distributed_file_daemon_manager.h | 41 + .../kits/native/remote_uri/remote_uri.h | 70 + .../include/input_method_agent_proxy.h | 13 +- .../include/i_input_method_system_ability.h | 15 + .../include/input_method_controller.h | 139 +- .../include/input_method_property.h | 47 + .../input_method_system_ability_proxy.h | 30 +- .../image_native/include/pixel_map.h | 3 +- .../system_ability_load_callback_stub.h | 8 +- .../startup_l2/syspara/include/parameter.h | 6 +- .../include/time_service_client.h | 37 +- .../libwm/include/window_manager.h | 67 +- .../libwm/include/wm_single_instance.h | 43 + mock/src/distributed_file_daemon_manager.cpp | 27 + mock/src/mock_aa_fwk.cpp | 1 + mock/src/mock_image..cpp | 8 + mock/src/mock_napi_base_context.cpp | 1 + mock/src/mock_notification.cpp | 10 + mock/src/mock_trace.cpp | 2 + mock/src/mock_uri_permission_manager.cpp | 5 + pasteboard/.gitattributes | 15 + pasteboard/.gitignore | 2 + pasteboard/BUILD.gn | 29 + pasteboard/CMakeLists.txt | 69 + pasteboard/CODEOWNERS | 15 + pasteboard/LICENSE | 177 ++ pasteboard/OAT.xml | 73 + pasteboard/README.md | 419 +++++ pasteboard/README_ZH.md | 768 +++++++++ pasteboard/bundle.json | 113 ++ pasteboard/etc/init/BUILD.gn | 23 + pasteboard/etc/init/pasteboardservice.cfg | 30 + pasteboard/etc/init/pasteboardservice.rc | 20 + pasteboard/figures/subsystem_architecture.png | Bin 0 -> 32044 bytes .../figures/subsystem_architecture_zh.png | Bin 0 -> 25627 bytes pasteboard/framework/framework/BUILD.gn | 84 + .../framework/framework/clip/clip_plugin.cpp | 79 + .../framework/framework/clip/default_clip.cpp | 35 + .../framework/framework/clip/default_clip.h | 28 + .../framework/framework/device/clip_para.cpp | 223 +++ .../framework/device/dev_manager.cpp | 200 +++ .../framework/device/dev_profile.cpp | 278 +++ .../device/distributed_module_config.cpp | 91 + .../framework/framework/device/dm_adapter.cpp | 198 +++ .../framework/device/para_handle.cpp | 63 + .../framework/include/api/visibility.h | 22 + .../framework/include/clip/clip_plugin.h | 66 + .../framework/include/common/block_object.h | 60 + .../framework/include/common/concurrent_map.h | 248 +++ .../framework/include/device/clip_para.h | 97 ++ .../framework/include/device/dev_manager.h | 45 + .../framework/include/device/dev_profile.h | 64 + .../device/distributed_module_config.h | 40 + .../framework/include/device/dm_adapter.h | 68 + .../framework/include/device/para_handle.h | 42 + .../include/serializable/serializable.h | 144 ++ .../framework/serializable/serializable.cpp | 236 +++ .../framework/test/dm_adapter_test.cpp | 55 + pasteboard/framework/innerkits/BUILD.gn | 84 + .../framework/innerkits/include/paste_data.h | 146 ++ .../innerkits/include/paste_data_record.h | 150 ++ .../innerkits/include/pasteboard_client.h | 282 +++ .../include/pasteboard_load_callback.h | 34 + .../innerkits/include/pasteboard_observer.h | 31 + .../include/pasteboard_web_controller.h | 55 + .../framework/innerkits/src/paste_data.cpp | 658 +++++++ .../innerkits/src/paste_data_record.cpp | 505 ++++++ .../innerkits/src/pasteboard_client.cpp | 461 +++++ .../src/pasteboard_load_callback.cpp | 35 + .../innerkits/src/pasteboard_observer.cpp | 36 + .../src/pasteboard_web_controller.cpp | 175 ++ pasteboard/framework/test/BUILD.gn | 88 + .../framework/test/include/clip_factory.h | 47 + .../framework/test/include/distributed_clip.h | 42 + .../framework/test/resource/ohos_test.xml | 22 + .../test/resource/pasteboardTest.txt | 14 + .../framework/test/src/clip_para_test.cpp | 309 ++++ .../framework/test/src/dm_adapter_test.cpp | 126 ++ .../framework/test/src/paste_data_test.cpp | 919 ++++++++++ .../test/src/pasteboard_client_test.cpp | 171 ++ .../framework/test/src/serializable_test.cpp | 381 ++++ .../framework/test/src/tlv_object_test.cpp | 169 ++ .../test/src/web_controller_test.cpp | 247 +++ pasteboard/framework/tlv/BUILD.gn | 50 + pasteboard/framework/tlv/endian_converter.h | 102 ++ pasteboard/framework/tlv/parcel_util.cpp | 57 + pasteboard/framework/tlv/parcel_util.h | 44 + pasteboard/framework/tlv/tlv_object.cpp | 241 +++ pasteboard/framework/tlv/tlv_object.h | 295 ++++ pasteboard/framework/uri/BUILD.gn | 59 + pasteboard/framework/uri/copy_uri_handler.cpp | 48 + pasteboard/framework/uri/copy_uri_handler.h | 27 + .../framework/uri/paste_uri_handler.cpp | 40 + pasteboard/framework/uri/paste_uri_handler.h | 25 + pasteboard/framework/uri/uri_handler.cpp | 83 + pasteboard/framework/uri/uri_handler.h | 38 + pasteboard/interfaces/kits/BUILD.gn | 74 + .../interfaces/kits/napi/include/async_call.h | 118 ++ .../interfaces/kits/napi/include/napi_init.h | 25 + .../kits/napi/include/pasteboard_common.h | 36 + .../kits/napi/include/pasteboard_js_err.h | 33 + .../kits/napi/include/pasteboard_napi.h | 68 + .../kits/napi/include/pastedata_napi.h | 79 + .../kits/napi/include/pastedata_record_napi.h | 64 + .../kits/napi/include/systempasteboard_napi.h | 163 ++ .../interfaces/kits/napi/src/async_call.cpp | 170 ++ .../interfaces/kits/napi/src/napi_init.cpp | 60 + .../kits/napi/src/napi_pasteboard.cpp | 484 ++++++ .../kits/napi/src/napi_pastedata.cpp | 1042 +++++++++++ .../kits/napi/src/napi_pastedata_record.cpp | 405 +++++ .../kits/napi/src/napi_systempasteboard.cpp | 767 +++++++++ .../kits/napi/src/pasteboard_common.cpp | 164 ++ .../kits/napi/test/unittest/config.json | 64 + .../napi/test/unittest/openharmony_sx.p7b | Bin 0 -> 3460 bytes .../napi/test/unittest/pasteboardapi/BUILD.gn | 29 + .../PasteBoardApiExceptionJsunit.test.js | 804 +++++++++ .../PasteBoardCallbackJsunit.test .js | 1129 ++++++++++++ .../PasteBoardPromiseJsunit.test.js | 1494 ++++++++++++++++ .../test/unittest/pasteboardperf/BUILD.gn | 29 + .../PasteBoardCallbackApiPerfJsunit.test.js | 275 +++ .../PasteBoardPromiseApiPerfJsunit.test.js | 277 +++ .../PasteBoardSyncApiPerfJsunit.test.js | 575 +++++++ pasteboard/pasteboard.gni | 48 + pasteboard/pasteboardEvent.yaml | 79 + pasteboard/profile/3701.json | 20 + pasteboard/profile/BUILD.gn | 19 + pasteboard/services/BUILD.gn | 150 ++ .../account/include/account_manager.h | 30 + .../services/account/src/account_manager.cpp | 27 + .../core/include/i_pasteboard_observer.h | 37 + .../core/include/i_pasteboard_service.h | 44 + .../pasteboard_common_event_subscriber.h | 34 + .../services/core/include/pasteboard_dialog.h | 52 + .../pasteboard_serv_ipc_interface_code.h | 46 + .../core/include/pasteboard_service.h | 205 +++ .../services/core/src/pasteboard_dialog.cpp | 118 ++ .../services/core/src/pasteboard_service.cpp | 1525 +++++++++++++++++ .../dfx/src/behaviour/behaviour_reporter.h | 32 + .../pasteboard_behaviour_reporter_impl.cpp | 29 + .../pasteboard_behaviour_reporter_impl.h | 30 + .../dfx/src/calculate_time_consuming.cpp | 123 ++ .../dfx/src/calculate_time_consuming.h | 56 + pasteboard/services/dfx/src/command.cpp | 55 + pasteboard/services/dfx/src/command.h | 44 + .../services/dfx/src/dfx_code_constant.h | 26 + pasteboard/services/dfx/src/dfx_types.h | 85 + .../services/dfx/src/fault/fault_reporter.h | 32 + .../dfx/src/fault/pasteboard_fault_impl.cpp | 29 + .../dfx/src/fault/pasteboard_fault_impl.h | 30 + .../services/dfx/src/hiview_adapter.cpp | 523 ++++++ pasteboard/services/dfx/src/hiview_adapter.h | 152 ++ .../dfx/src/pasteboard_dump_helper.cpp | 52 + .../services/dfx/src/pasteboard_dump_helper.h | 40 + .../services/dfx/src/pasteboard_trace.cpp | 56 + .../services/dfx/src/pasteboard_trace.h | 35 + pasteboard/services/dfx/src/reporter.cpp | 48 + pasteboard/services/dfx/src/reporter.h | 37 + .../dfx/src/statistic/statistic_reporter.h | 33 + .../time_consuming_statistic_impl.cpp | 29 + .../statistic/time_consuming_statistic_impl.h | 33 + pasteboard/services/dialog/BUILD.gn | 51 + .../dialog/PasteboardDialog/.gitignore | 5 + .../dialog/PasteboardDialog/AppScope/app.json | 13 + .../resources/base/element/string.json | 8 + .../resources/base/media/app_icon.png | Bin 0 -> 6790 bytes .../PasteboardDialog/build-profile.json5 | 41 + .../dialog/PasteboardDialog/entry/.gitignore | 4 + .../entry/build-profile.json5 | 24 + .../PasteboardDialog/entry/hvigorfile.js | 2 + .../PasteboardDialog/entry/package-lock.json | 5 + .../PasteboardDialog/entry/package.json | 13 + .../main/ets/Application/MyAbilityStage.ts | 23 + .../main/ets/ServiceExtAbility/GlobalParam.ts | 45 + .../ToastExtensionAbility.ts | 142 ++ .../entry/src/main/ets/pages/index.ets | 59 + .../entry/src/main/module.json | 29 + .../main/resources/base/element/color.json | 12 + .../main/resources/base/element/string.json | 54 + .../main/resources/base/media/btn_cancel.svg | 13 + .../src/main/resources/base/media/icon.png | Bin 0 -> 6790 bytes .../resources/base/profile/main_pages.json | 5 + .../src/main/resources/zh/element/string.json | 52 + .../dialog/PasteboardDialog/hvigorfile.js | 2 + .../dialog/PasteboardDialog/package-lock.json | 1226 +++++++++++++ .../dialog/PasteboardDialog/package.json | 17 + .../signature/com.ohos.pasteboarddialog.p7b | Bin 0 -> 3430 bytes pasteboard/services/etc/BUILD.gn | 20 + pasteboard/services/etc/pasteboard.para.dac | 14 + pasteboard/services/load/include/config.h | 41 + pasteboard/services/load/include/loader.h | 32 + pasteboard/services/load/src/config.cpp | 57 + pasteboard/services/load/src/loader.cpp | 71 + pasteboard/services/test/BUILD.gn | 75 + .../include/pasteboard_observer_callback.h | 45 + .../services/test/unittest/src/dfx_test.cpp | 199 +++ .../test/unittest/src/paste_service_test.cpp | 1321 ++++++++++++++ .../zidl/include/pasteboard_observer_proxy.h | 41 + .../zidl/include/pasteboard_observer_stub.h | 42 + .../zidl/include/pasteboard_service_proxy.h | 50 + .../zidl/include/pasteboard_service_stub.h | 59 + .../zidl/src/pasteboard_observer_proxy.cpp | 73 + .../zidl/src/pasteboard_observer_stub.cpp | 82 + .../zidl/src/pasteboard_service_proxy.cpp | 301 ++++ .../zidl/src/pasteboard_service_stub.cpp | 293 ++++ pasteboard/test/fuzztest/BUILD.gn | 24 + .../fuzztest/pasteboardclient_fuzzer/BUILD.gn | 66 + .../pasteboardclient_fuzzer/corpus/init | 14 + .../pasteboardclient_fuzzer.cpp | 173 ++ .../pasteboardclient_fuzzer.h | 21 + .../pasteboardclient_fuzzer/project.xml | 25 + .../pasteboardservice_fuzzer/BUILD.gn | 77 + .../pasteboardservice_fuzzer/corpus/init | 14 + .../pasteboardservice_fuzzer.cpp | 181 ++ .../pasteboardservice_fuzzer.h | 21 + .../pasteboardservice_fuzzer/project.xml | 25 + .../test/fuzztest/urihandler_fuzzer/BUILD.gn | 63 + .../fuzztest/urihandler_fuzzer/corpus/init | 14 + .../fuzztest/urihandler_fuzzer/project.xml | 25 + .../urihandler_fuzzer/urihandler_fuzzer.cpp | 56 + .../urihandler_fuzzer/urihandler_fuzzer.h | 21 + .../utils/native/include/pasteboard_error.h | 74 + .../utils/native/include/pasteboard_hilog.h | 76 + .../native/include/pasteboard_sp_singleton.h | 76 + 230 files changed, 29211 insertions(+), 128 deletions(-) create mode 100644 mock/innerkits/ability_runtime/napi_common/in_process_call_wrapper.h create mode 100644 mock/innerkits/filemanagement/dfs_service/services/distributedfiledaemon/include/ipc/distributed_file_daemon_manager.h create mode 100644 mock/innerkits/filemanagement/file_api/interfaces/kits/native/remote_uri/remote_uri.h create mode 100644 mock/innerkits/inputmethod_native/inputmethod_client/include/i_input_method_system_ability.h create mode 100644 mock/innerkits/inputmethod_native/inputmethod_client/include/input_method_property.h create mode 100644 mock/innerkits/window_manager/libwm/include/wm_single_instance.h create mode 100644 mock/src/distributed_file_daemon_manager.cpp create mode 100644 pasteboard/.gitattributes create mode 100644 pasteboard/.gitignore create mode 100644 pasteboard/BUILD.gn create mode 100644 pasteboard/CMakeLists.txt create mode 100644 pasteboard/CODEOWNERS create mode 100644 pasteboard/LICENSE create mode 100644 pasteboard/OAT.xml create mode 100644 pasteboard/README.md create mode 100644 pasteboard/README_ZH.md create mode 100644 pasteboard/bundle.json create mode 100644 pasteboard/etc/init/BUILD.gn create mode 100644 pasteboard/etc/init/pasteboardservice.cfg create mode 100644 pasteboard/etc/init/pasteboardservice.rc create mode 100644 pasteboard/figures/subsystem_architecture.png create mode 100644 pasteboard/figures/subsystem_architecture_zh.png create mode 100644 pasteboard/framework/framework/BUILD.gn create mode 100644 pasteboard/framework/framework/clip/clip_plugin.cpp create mode 100644 pasteboard/framework/framework/clip/default_clip.cpp create mode 100644 pasteboard/framework/framework/clip/default_clip.h create mode 100644 pasteboard/framework/framework/device/clip_para.cpp create mode 100644 pasteboard/framework/framework/device/dev_manager.cpp create mode 100644 pasteboard/framework/framework/device/dev_profile.cpp create mode 100644 pasteboard/framework/framework/device/distributed_module_config.cpp create mode 100644 pasteboard/framework/framework/device/dm_adapter.cpp create mode 100644 pasteboard/framework/framework/device/para_handle.cpp create mode 100644 pasteboard/framework/framework/include/api/visibility.h create mode 100644 pasteboard/framework/framework/include/clip/clip_plugin.h create mode 100644 pasteboard/framework/framework/include/common/block_object.h create mode 100644 pasteboard/framework/framework/include/common/concurrent_map.h create mode 100644 pasteboard/framework/framework/include/device/clip_para.h create mode 100644 pasteboard/framework/framework/include/device/dev_manager.h create mode 100644 pasteboard/framework/framework/include/device/dev_profile.h create mode 100644 pasteboard/framework/framework/include/device/distributed_module_config.h create mode 100644 pasteboard/framework/framework/include/device/dm_adapter.h create mode 100644 pasteboard/framework/framework/include/device/para_handle.h create mode 100644 pasteboard/framework/framework/include/serializable/serializable.h create mode 100644 pasteboard/framework/framework/serializable/serializable.cpp create mode 100644 pasteboard/framework/framework/test/dm_adapter_test.cpp create mode 100644 pasteboard/framework/innerkits/BUILD.gn create mode 100644 pasteboard/framework/innerkits/include/paste_data.h create mode 100644 pasteboard/framework/innerkits/include/paste_data_record.h create mode 100644 pasteboard/framework/innerkits/include/pasteboard_client.h create mode 100644 pasteboard/framework/innerkits/include/pasteboard_load_callback.h create mode 100644 pasteboard/framework/innerkits/include/pasteboard_observer.h create mode 100644 pasteboard/framework/innerkits/include/pasteboard_web_controller.h create mode 100644 pasteboard/framework/innerkits/src/paste_data.cpp create mode 100644 pasteboard/framework/innerkits/src/paste_data_record.cpp create mode 100644 pasteboard/framework/innerkits/src/pasteboard_client.cpp create mode 100644 pasteboard/framework/innerkits/src/pasteboard_load_callback.cpp create mode 100644 pasteboard/framework/innerkits/src/pasteboard_observer.cpp create mode 100644 pasteboard/framework/innerkits/src/pasteboard_web_controller.cpp create mode 100644 pasteboard/framework/test/BUILD.gn create mode 100644 pasteboard/framework/test/include/clip_factory.h create mode 100644 pasteboard/framework/test/include/distributed_clip.h create mode 100644 pasteboard/framework/test/resource/ohos_test.xml create mode 100644 pasteboard/framework/test/resource/pasteboardTest.txt create mode 100644 pasteboard/framework/test/src/clip_para_test.cpp create mode 100644 pasteboard/framework/test/src/dm_adapter_test.cpp create mode 100644 pasteboard/framework/test/src/paste_data_test.cpp create mode 100644 pasteboard/framework/test/src/pasteboard_client_test.cpp create mode 100644 pasteboard/framework/test/src/serializable_test.cpp create mode 100644 pasteboard/framework/test/src/tlv_object_test.cpp create mode 100644 pasteboard/framework/test/src/web_controller_test.cpp create mode 100644 pasteboard/framework/tlv/BUILD.gn create mode 100644 pasteboard/framework/tlv/endian_converter.h create mode 100644 pasteboard/framework/tlv/parcel_util.cpp create mode 100644 pasteboard/framework/tlv/parcel_util.h create mode 100644 pasteboard/framework/tlv/tlv_object.cpp create mode 100644 pasteboard/framework/tlv/tlv_object.h create mode 100644 pasteboard/framework/uri/BUILD.gn create mode 100644 pasteboard/framework/uri/copy_uri_handler.cpp create mode 100644 pasteboard/framework/uri/copy_uri_handler.h create mode 100644 pasteboard/framework/uri/paste_uri_handler.cpp create mode 100644 pasteboard/framework/uri/paste_uri_handler.h create mode 100644 pasteboard/framework/uri/uri_handler.cpp create mode 100644 pasteboard/framework/uri/uri_handler.h create mode 100644 pasteboard/interfaces/kits/BUILD.gn create mode 100644 pasteboard/interfaces/kits/napi/include/async_call.h create mode 100644 pasteboard/interfaces/kits/napi/include/napi_init.h create mode 100644 pasteboard/interfaces/kits/napi/include/pasteboard_common.h create mode 100644 pasteboard/interfaces/kits/napi/include/pasteboard_js_err.h create mode 100644 pasteboard/interfaces/kits/napi/include/pasteboard_napi.h create mode 100644 pasteboard/interfaces/kits/napi/include/pastedata_napi.h create mode 100644 pasteboard/interfaces/kits/napi/include/pastedata_record_napi.h create mode 100644 pasteboard/interfaces/kits/napi/include/systempasteboard_napi.h create mode 100644 pasteboard/interfaces/kits/napi/src/async_call.cpp create mode 100644 pasteboard/interfaces/kits/napi/src/napi_init.cpp create mode 100644 pasteboard/interfaces/kits/napi/src/napi_pasteboard.cpp create mode 100644 pasteboard/interfaces/kits/napi/src/napi_pastedata.cpp create mode 100644 pasteboard/interfaces/kits/napi/src/napi_pastedata_record.cpp create mode 100644 pasteboard/interfaces/kits/napi/src/napi_systempasteboard.cpp create mode 100644 pasteboard/interfaces/kits/napi/src/pasteboard_common.cpp create mode 100644 pasteboard/interfaces/kits/napi/test/unittest/config.json create mode 100644 pasteboard/interfaces/kits/napi/test/unittest/openharmony_sx.p7b create mode 100644 pasteboard/interfaces/kits/napi/test/unittest/pasteboardapi/BUILD.gn create mode 100644 pasteboard/interfaces/kits/napi/test/unittest/pasteboardapi/PasteBoardApiExceptionJsunit.test.js create mode 100644 pasteboard/interfaces/kits/napi/test/unittest/pasteboardapi/PasteBoardCallbackJsunit.test .js create mode 100644 pasteboard/interfaces/kits/napi/test/unittest/pasteboardapi/PasteBoardPromiseJsunit.test.js create mode 100644 pasteboard/interfaces/kits/napi/test/unittest/pasteboardperf/BUILD.gn create mode 100644 pasteboard/interfaces/kits/napi/test/unittest/pasteboardperf/PasteBoardCallbackApiPerfJsunit.test.js create mode 100644 pasteboard/interfaces/kits/napi/test/unittest/pasteboardperf/PasteBoardPromiseApiPerfJsunit.test.js create mode 100644 pasteboard/interfaces/kits/napi/test/unittest/pasteboardperf/PasteBoardSyncApiPerfJsunit.test.js create mode 100644 pasteboard/pasteboard.gni create mode 100644 pasteboard/pasteboardEvent.yaml create mode 100644 pasteboard/profile/3701.json create mode 100644 pasteboard/profile/BUILD.gn create mode 100644 pasteboard/services/BUILD.gn create mode 100644 pasteboard/services/account/include/account_manager.h create mode 100644 pasteboard/services/account/src/account_manager.cpp create mode 100644 pasteboard/services/core/include/i_pasteboard_observer.h create mode 100644 pasteboard/services/core/include/i_pasteboard_service.h create mode 100644 pasteboard/services/core/include/pasteboard_common_event_subscriber.h create mode 100644 pasteboard/services/core/include/pasteboard_dialog.h create mode 100644 pasteboard/services/core/include/pasteboard_serv_ipc_interface_code.h create mode 100644 pasteboard/services/core/include/pasteboard_service.h create mode 100644 pasteboard/services/core/src/pasteboard_dialog.cpp create mode 100644 pasteboard/services/core/src/pasteboard_service.cpp create mode 100644 pasteboard/services/dfx/src/behaviour/behaviour_reporter.h create mode 100644 pasteboard/services/dfx/src/behaviour/pasteboard_behaviour_reporter_impl.cpp create mode 100644 pasteboard/services/dfx/src/behaviour/pasteboard_behaviour_reporter_impl.h create mode 100644 pasteboard/services/dfx/src/calculate_time_consuming.cpp create mode 100644 pasteboard/services/dfx/src/calculate_time_consuming.h create mode 100644 pasteboard/services/dfx/src/command.cpp create mode 100644 pasteboard/services/dfx/src/command.h create mode 100644 pasteboard/services/dfx/src/dfx_code_constant.h create mode 100644 pasteboard/services/dfx/src/dfx_types.h create mode 100644 pasteboard/services/dfx/src/fault/fault_reporter.h create mode 100644 pasteboard/services/dfx/src/fault/pasteboard_fault_impl.cpp create mode 100644 pasteboard/services/dfx/src/fault/pasteboard_fault_impl.h create mode 100644 pasteboard/services/dfx/src/hiview_adapter.cpp create mode 100644 pasteboard/services/dfx/src/hiview_adapter.h create mode 100644 pasteboard/services/dfx/src/pasteboard_dump_helper.cpp create mode 100644 pasteboard/services/dfx/src/pasteboard_dump_helper.h create mode 100644 pasteboard/services/dfx/src/pasteboard_trace.cpp create mode 100644 pasteboard/services/dfx/src/pasteboard_trace.h create mode 100644 pasteboard/services/dfx/src/reporter.cpp create mode 100644 pasteboard/services/dfx/src/reporter.h create mode 100644 pasteboard/services/dfx/src/statistic/statistic_reporter.h create mode 100644 pasteboard/services/dfx/src/statistic/time_consuming_statistic_impl.cpp create mode 100644 pasteboard/services/dfx/src/statistic/time_consuming_statistic_impl.h create mode 100644 pasteboard/services/dialog/BUILD.gn create mode 100644 pasteboard/services/dialog/PasteboardDialog/.gitignore create mode 100644 pasteboard/services/dialog/PasteboardDialog/AppScope/app.json create mode 100644 pasteboard/services/dialog/PasteboardDialog/AppScope/resources/base/element/string.json create mode 100644 pasteboard/services/dialog/PasteboardDialog/AppScope/resources/base/media/app_icon.png create mode 100644 pasteboard/services/dialog/PasteboardDialog/build-profile.json5 create mode 100644 pasteboard/services/dialog/PasteboardDialog/entry/.gitignore create mode 100644 pasteboard/services/dialog/PasteboardDialog/entry/build-profile.json5 create mode 100644 pasteboard/services/dialog/PasteboardDialog/entry/hvigorfile.js create mode 100644 pasteboard/services/dialog/PasteboardDialog/entry/package-lock.json create mode 100644 pasteboard/services/dialog/PasteboardDialog/entry/package.json create mode 100644 pasteboard/services/dialog/PasteboardDialog/entry/src/main/ets/Application/MyAbilityStage.ts create mode 100644 pasteboard/services/dialog/PasteboardDialog/entry/src/main/ets/ServiceExtAbility/GlobalParam.ts create mode 100644 pasteboard/services/dialog/PasteboardDialog/entry/src/main/ets/ServiceExtAbility/ToastExtensionAbility.ts create mode 100644 pasteboard/services/dialog/PasteboardDialog/entry/src/main/ets/pages/index.ets create mode 100644 pasteboard/services/dialog/PasteboardDialog/entry/src/main/module.json create mode 100644 pasteboard/services/dialog/PasteboardDialog/entry/src/main/resources/base/element/color.json create mode 100644 pasteboard/services/dialog/PasteboardDialog/entry/src/main/resources/base/element/string.json create mode 100644 pasteboard/services/dialog/PasteboardDialog/entry/src/main/resources/base/media/btn_cancel.svg create mode 100644 pasteboard/services/dialog/PasteboardDialog/entry/src/main/resources/base/media/icon.png create mode 100644 pasteboard/services/dialog/PasteboardDialog/entry/src/main/resources/base/profile/main_pages.json create mode 100644 pasteboard/services/dialog/PasteboardDialog/entry/src/main/resources/zh/element/string.json create mode 100644 pasteboard/services/dialog/PasteboardDialog/hvigorfile.js create mode 100644 pasteboard/services/dialog/PasteboardDialog/package-lock.json create mode 100644 pasteboard/services/dialog/PasteboardDialog/package.json create mode 100644 pasteboard/services/dialog/PasteboardDialog/signature/com.ohos.pasteboarddialog.p7b create mode 100644 pasteboard/services/etc/BUILD.gn create mode 100644 pasteboard/services/etc/pasteboard.para.dac create mode 100644 pasteboard/services/load/include/config.h create mode 100644 pasteboard/services/load/include/loader.h create mode 100644 pasteboard/services/load/src/config.cpp create mode 100644 pasteboard/services/load/src/loader.cpp create mode 100644 pasteboard/services/test/BUILD.gn create mode 100644 pasteboard/services/test/unittest/include/pasteboard_observer_callback.h create mode 100644 pasteboard/services/test/unittest/src/dfx_test.cpp create mode 100644 pasteboard/services/test/unittest/src/paste_service_test.cpp create mode 100644 pasteboard/services/zidl/include/pasteboard_observer_proxy.h create mode 100644 pasteboard/services/zidl/include/pasteboard_observer_stub.h create mode 100644 pasteboard/services/zidl/include/pasteboard_service_proxy.h create mode 100644 pasteboard/services/zidl/include/pasteboard_service_stub.h create mode 100644 pasteboard/services/zidl/src/pasteboard_observer_proxy.cpp create mode 100644 pasteboard/services/zidl/src/pasteboard_observer_stub.cpp create mode 100644 pasteboard/services/zidl/src/pasteboard_service_proxy.cpp create mode 100644 pasteboard/services/zidl/src/pasteboard_service_stub.cpp create mode 100644 pasteboard/test/fuzztest/BUILD.gn create mode 100644 pasteboard/test/fuzztest/pasteboardclient_fuzzer/BUILD.gn create mode 100644 pasteboard/test/fuzztest/pasteboardclient_fuzzer/corpus/init create mode 100644 pasteboard/test/fuzztest/pasteboardclient_fuzzer/pasteboardclient_fuzzer.cpp create mode 100644 pasteboard/test/fuzztest/pasteboardclient_fuzzer/pasteboardclient_fuzzer.h create mode 100644 pasteboard/test/fuzztest/pasteboardclient_fuzzer/project.xml create mode 100644 pasteboard/test/fuzztest/pasteboardservice_fuzzer/BUILD.gn create mode 100644 pasteboard/test/fuzztest/pasteboardservice_fuzzer/corpus/init create mode 100644 pasteboard/test/fuzztest/pasteboardservice_fuzzer/pasteboardservice_fuzzer.cpp create mode 100644 pasteboard/test/fuzztest/pasteboardservice_fuzzer/pasteboardservice_fuzzer.h create mode 100644 pasteboard/test/fuzztest/pasteboardservice_fuzzer/project.xml create mode 100644 pasteboard/test/fuzztest/urihandler_fuzzer/BUILD.gn create mode 100644 pasteboard/test/fuzztest/urihandler_fuzzer/corpus/init create mode 100644 pasteboard/test/fuzztest/urihandler_fuzzer/project.xml create mode 100644 pasteboard/test/fuzztest/urihandler_fuzzer/urihandler_fuzzer.cpp create mode 100644 pasteboard/test/fuzztest/urihandler_fuzzer/urihandler_fuzzer.h create mode 100644 pasteboard/utils/native/include/pasteboard_error.h create mode 100644 pasteboard/utils/native/include/pasteboard_hilog.h create mode 100644 pasteboard/utils/native/include/pasteboard_sp_singleton.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 1784ebef..e7c93ae6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,6 +19,7 @@ add_subdirectory(preferences) add_subdirectory(data_object) add_subdirectory(datamgr_service) add_subdirectory(udmf) +add_subdirectory(pasteboard) set(CMAKE_CXX_FLAGS "-std=c++1y -fno-rtti -fvisibility=default -D_GNU_SOURCE") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdata-sections -fPIC -fpic -ffunction-sections -D_GLIBC_MOCK") @@ -34,7 +35,7 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}/mock/innerkits/ipc/ipc_single/in include_directories(${CMAKE_CURRENT_SOURCE_DIR}/mock/innerkits/ipc/libdbinder/include) set(MAIN_BINARY ${PROJECT_NAME}) -set(links secure mock relational_store data_share preferences jsoncpp crypto distributeddb data_object app adapter svcFwk kvdb service udmf) +set(links secure mock relational_store data_share preferences jsoncpp crypto distributeddb data_object app adapter svcFwk kvdb service udmf pasteboard) add_executable(${MAIN_BINARY} dllmain.cpp) target_link_libraries(${MAIN_BINARY} ${links}) diff --git a/mock/CMakeLists.txt b/mock/CMakeLists.txt index e2594e3d..0680f586 100644 --- a/mock/CMakeLists.txt +++ b/mock/CMakeLists.txt @@ -240,6 +240,8 @@ target_include_directories(mock PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/innerkits/fil target_include_directories(mock PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/innerkits/filemanagement/app_file_service/interfaces/innerkits/native/remote_file_share/include) target_include_directories(mock PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/innerkits/filemanagement/dfs_service/interfaces/inner_api/native/cloudsync_kit_inner) target_include_directories(mock PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/innerkits/filemanagement/dfs_service/frameworks/native/cloudsync_kit_inner/include) +target_include_directories(mock PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/innerkits/filemanagement/dfs_service/services/distributedfiledaemon/include/ipc) +target_include_directories(mock PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/innerkits/filemanagement/file_api/interfaces/kits/native/remote_uri) target_include_directories(mock PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/kits) target_include_directories(mock PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/kits/ability/ability_runtime) target_include_directories(mock PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/kits/ability) diff --git a/mock/include/CMakeLists.txt b/mock/include/CMakeLists.txt index ec05b925..f91a14fc 100644 --- a/mock/include/CMakeLists.txt +++ b/mock/include/CMakeLists.txt @@ -222,4 +222,7 @@ include_directories(${MOCK_DIR}/sqlite/include) include_directories(${MOCK_DIR}/innerkits/filemanagement/file_api/interfaces/kits) include_directories(${MOCK_DIR}/innerkits/filemanagement/app_file_service/interfaces/innerkits/native/remote_file_share/include) include_directories(${MOCK_DIR}/innerkits/filemanagement/app_file_service/interfaces/innerkits/native/file_uri/include) -include_directories(${MOCK_DIR}/innerkits/filemanagement/app_file_service/interfaces/common/include) \ No newline at end of file +include_directories(${MOCK_DIR}/innerkits/filemanagement/app_file_service/interfaces/common/include) + +include_directories(${MOCK_DIR}/innerkits/startup_l2/syspara_watchagent/include) +include_directories(${MOCK_DIR}/innerkits/startup_l2/syspara/include) \ No newline at end of file diff --git a/mock/innerkits/ability_base/base/include/int_wrapper.h b/mock/innerkits/ability_base/base/include/int_wrapper.h index 5960f50d..41ae053a 100644 --- a/mock/innerkits/ability_base/base/include/int_wrapper.h +++ b/mock/innerkits/ability_base/base/include/int_wrapper.h @@ -48,6 +48,7 @@ public: private: int value_; }; +sptr Integer::Box(int value) { return sptr(); } } // namespace AAFwk } // namespace OHOS #endif // OHOS_AAFWK_INTEGER_H \ No newline at end of file diff --git a/mock/innerkits/ability_runtime/ability_manager/include/ability_manager_client.h b/mock/innerkits/ability_runtime/ability_manager/include/ability_manager_client.h index d6871a1e..e79a79ef 100644 --- a/mock/innerkits/ability_runtime/ability_manager/include/ability_manager_client.h +++ b/mock/innerkits/ability_runtime/ability_manager/include/ability_manager_client.h @@ -39,7 +39,14 @@ public: AbilityManagerClient(); virtual ~AbilityManagerClient(); static std::shared_ptr GetInstance(); - + struct Property { + std::string name; // the bundleName of inputMethod + std::string id; // the extensionName of inputMethod + std::string label; // the label of inputMethod + int32_t labelId = 0; // the labelId of inputMethod + std::string icon; // the icon of inputMethod + int32_t iconId = 0; // the icon id of inputMethod + }; /** * AttachAbilityThread, ability call this interface after loaded. * @@ -411,6 +418,17 @@ public: * @return Returns ERR_OK on success, others on failure. */ ErrCode ContinueAbility(const std::string &deviceId, int32_t missionId, uint32_t versionCode); + /** + * @brief Get current input method property. + * + * This function is used to get current input method property. + * + * @return The property of current input method. + * @since 6 + */ + std::shared_ptr GetCurrentInputMethod(); + + ErrCode CheckUIExtensionIsFocused(uint32_t uiExtensionTokenId, bool& isFocused); /** * notify continuation result to application. diff --git a/mock/innerkits/ability_runtime/napi_common/in_process_call_wrapper.h b/mock/innerkits/ability_runtime/napi_common/in_process_call_wrapper.h new file mode 100644 index 00000000..19375192 --- /dev/null +++ b/mock/innerkits/ability_runtime/napi_common/in_process_call_wrapper.h @@ -0,0 +1,36 @@ +/* +* Copyright (c) 2022 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef OHOS_ABILITY_RUNTIME_IN_PROCESS_CALL_WRAPPER_H +#define OHOS_ABILITY_RUNTIME_IN_PROCESS_CALL_WRAPPER_H + +#include "ipc_skeleton.h" + +#define IN_PROCESS_CALL(theCall) \ + ([&]() { \ + std::string identity = IPCSkeleton::ResetCallingIdentity(); \ + auto retVal = theCall; \ + IPCSkeleton::SetCallingIdentity(identity); \ + return retVal; \ + }()) + +#define IN_PROCESS_CALL_WITHOUT_RET(theCall) \ + do { \ + std::string identity = IPCSkeleton::ResetCallingIdentity(); \ + theCall; \ + IPCSkeleton::SetCallingIdentity(identity); \ + } while (0) + +#endif // OHOS_ABILITY_RUNTIME_IN_PROCESS_CALL_WRAPPER_H diff --git a/mock/innerkits/appexecfwk_core/include/bundlemgr/bundle_mgr_interface.h b/mock/innerkits/appexecfwk_core/include/bundlemgr/bundle_mgr_interface.h index b46fa015..06c36139 100644 --- a/mock/innerkits/appexecfwk_core/include/bundlemgr/bundle_mgr_interface.h +++ b/mock/innerkits/appexecfwk_core/include/bundlemgr/bundle_mgr_interface.h @@ -936,7 +936,11 @@ public: { return ERR_APPEXECFWK_SANDBOX_QUERY_PARAM_ERROR; } - + virtual std::string GetStringById(const std::string &bundleName, const std::string &moduleName, uint32_t resId, + int32_t userId, const std::string &localeInfo = Constants::EMPTY_STRING) + { + return Constants::EMPTY_STRING; + } virtual ErrCode GetSandboxExtAbilityInfos(const Want &want, int32_t appIndex, int32_t flags, int32_t userId, std::vector &einfos) { diff --git a/mock/innerkits/filemanagement/dfs_service/services/distributedfiledaemon/include/ipc/distributed_file_daemon_manager.h b/mock/innerkits/filemanagement/dfs_service/services/distributedfiledaemon/include/ipc/distributed_file_daemon_manager.h new file mode 100644 index 00000000..ede9cf75 --- /dev/null +++ b/mock/innerkits/filemanagement/dfs_service/services/distributedfiledaemon/include/ipc/distributed_file_daemon_manager.h @@ -0,0 +1,41 @@ +/* +* Copyright (c) 2023 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef DISTRIBUTED_FILE_DAEMON_MANAGER_H +#define DISTRIBUTED_FILE_DAEMON_MANAGER_H + +#include + +#include "dm_device_info.h" +//#include "i_file_trans_listener.h" +namespace OHOS { +namespace Storage { +namespace DistributedFile { +class DistributedFileDaemonManager { +public: + static DistributedFileDaemonManager &GetInstance(); + + int32_t OpenP2PConnection(const DistributedHardware::DmDeviceInfo &deviceInfo); + int32_t CloseP2PConnection(const DistributedHardware::DmDeviceInfo &deviceInfo); +// virtual int32_t PrepareSession(const std::string &srcUri, +// const std::string &dstUri, +// const std::string &srcDeviceId, +// const sptr &listener) = 0; +}; +} // namespace DistributedFile +} // namespace Storage +} // namespace OHOS + +#endif // DISTRIBUTED_FILE_DAEMON_MANAGER_H \ No newline at end of file diff --git a/mock/innerkits/filemanagement/file_api/interfaces/kits/native/remote_uri/remote_uri.h b/mock/innerkits/filemanagement/file_api/interfaces/kits/native/remote_uri/remote_uri.h new file mode 100644 index 00000000..b28742b0 --- /dev/null +++ b/mock/innerkits/filemanagement/file_api/interfaces/kits/native/remote_uri/remote_uri.h @@ -0,0 +1,70 @@ +// +// Created by wangh on 2024/3/23. +// + +#ifndef LDBPROJ_REMOTE_URI_H +#define LDBPROJ_REMOTE_URI_H + +#endif //LDBPROJ_REMOTE_URI_H +/* +* Copyright (c) 2022-2023 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef REMOTE_URI_H +#define REMOTE_URI_H + +#include +#include +#include +#include "uri.h" + + namespace OHOS { + namespace DistributedFS { + namespace ModuleRemoteUri { + + using namespace std; + + const string FRAGMENT_TAG = "#"; + const string FD_TAG = "="; + const string REMOTE_URI_TAG = "fdFromBinder"; + const string SCHEME_TAG = ":"; + const string SCHEME = "datashare"; + const string SCHEME_FILE = "file"; + const string MEDIALIBRARY_FILE_URI_PREFIX = "file://media"; + const string ZERO_FD = "0"; + const string MEDIA = "/media/"; + const string PATH_SYMBOL = "/"; + const int MAX_URI_SIZE = 128; + class RemoteUri : public OHOS::Uri { + static setfdFromBinder; + static void RemoveFd(int fd); + public: + explicit RemoteUri(const std::string& uriString): Uri(uriString) {} + static bool IsRemoteUri(const string& path, int &fd, const int& flags = O_RDONLY); + static int ConvertUri(const int &fd, string &remoteUri); + static int OpenRemoteUri(const string &remoteUri); + static bool IsMediaUri(const string &uriString); + static bool IsFileUri(const string &uriString); + ~RemoteUri() {} + }; + int RemoteUri::ConvertUri(const int& fd, string& remoteUri) + { + return 0; + } + std::setRemoteUri::fdFromBinder; + } // namespace ModuleRemoteUri + } // namespace DistributedFS +} // namespace OHOS + +#endif \ No newline at end of file diff --git a/mock/innerkits/inputmethod_native/inputmethod_ability/include/input_method_agent_proxy.h b/mock/innerkits/inputmethod_native/inputmethod_ability/include/input_method_agent_proxy.h index b432a87f..00ca3633 100644 --- a/mock/innerkits/inputmethod_native/inputmethod_ability/include/input_method_agent_proxy.h +++ b/mock/innerkits/inputmethod_native/inputmethod_ability/include/input_method_agent_proxy.h @@ -35,6 +35,17 @@ namespace MiscServices { private: static inline BrokerDelegator delegator_; }; -} // namespace MiscServices + InputMethodAgentProxy::InputMethodAgentProxy(const sptr& object) : IRemoteProxy(object) {} + bool InputMethodAgentProxy::DispatchKeyEvent(MessageParcel& data) + { + return false; + } + void InputMethodAgentProxy::OnCursorUpdate(int32_t positionX, int32_t positionY, int32_t height) {} + void InputMethodAgentProxy::OnSelectionChange(std::u16string text, int32_t oldBegin, int32_t oldEnd, + int32_t newBegin, int32_t newEnd) + { + } + void InputMethodAgentProxy::SetCallingWindow(uint32_t windowId) {} + } // namespace MiscServices } // namespace OHOS #endif // FRAMEWORKS_INPUTMETHOD_ABILITY_INCLUDE_INPUT_METHOD_AGENT_PROXY_H diff --git a/mock/innerkits/inputmethod_native/inputmethod_client/include/i_input_method_system_ability.h b/mock/innerkits/inputmethod_native/inputmethod_client/include/i_input_method_system_ability.h new file mode 100644 index 00000000..336bbbca --- /dev/null +++ b/mock/innerkits/inputmethod_native/inputmethod_client/include/i_input_method_system_ability.h @@ -0,0 +1,15 @@ +// +// Created by wangh on 2024/3/23. +// + +#include "iremote_broker.h" +#ifndef LDBPROJ_I_INPUT_METHOD_SYSTEM_ABILITY_H +#define LDBPROJ_I_INPUT_METHOD_SYSTEM_ABILITY_H + +#endif //LDBPROJ_I_INPUT_METHOD_SYSTEM_ABILITY_H +namespace OHOS { +namespace MiscServices { +class IInputMethodSystemAbility : public IRemoteBroker {}; + +} +} \ No newline at end of file diff --git a/mock/innerkits/inputmethod_native/inputmethod_client/include/input_method_controller.h b/mock/innerkits/inputmethod_native/inputmethod_client/include/input_method_controller.h index 6fdb1940..e13c518f 100644 --- a/mock/innerkits/inputmethod_native/inputmethod_client/include/input_method_controller.h +++ b/mock/innerkits/inputmethod_native/inputmethod_client/include/input_method_controller.h @@ -25,6 +25,7 @@ #include "input_client_stub.h" #include "input_data_channel_stub.h" #include "input_method_agent_proxy.h" +#include "input_method_property.h" #include "input_method_system_ability_proxy.h" #include "input_method_utils.h" #include "ipc_skeleton.h" @@ -38,80 +39,90 @@ namespace MiscServices { class InputMethodSystemAbilityProxy; class OnTextChangedListener : public virtual RefBase { public: - virtual void InsertText(const std::u16string& text) = 0; - virtual void DeleteForward(int32_t length) = 0; - virtual void DeleteBackward(int32_t length) = 0; - virtual void SendKeyEventFromInputMethod(const KeyEvent& event) = 0; - virtual void SendKeyboardInfo(const KeyboardInfo& info) = 0; - virtual void SetKeyboardStatus(bool status) = 0; - virtual void MoveCursor(const Direction direction) = 0; +// virtual void InsertText(const std::u16string& text) = 0; +// virtual void DeleteForward(int32_t length) = 0; +// virtual void DeleteBackward(int32_t length) = 0; +// virtual void SendKeyEventFromInputMethod(const KeyEvent& event) = 0; +// virtual void SendKeyboardInfo(const KeyboardInfo& info) = 0; +// virtual void SetKeyboardStatus(bool status) = 0; +// virtual void MoveCursor(const Direction direction) = 0; }; - class ImsaDeathRecipient : public IRemoteObject::DeathRecipient { - public: - explicit ImsaDeathRecipient(); - ~ImsaDeathRecipient() = default; - - void OnRemoteDied(const wptr &object) override; - }; +// class ImsaDeathRecipient : public IRemoteObject::DeathRecipient { +// public: +// explicit ImsaDeathRecipient(); +// ~ImsaDeathRecipient() = default; +// +// void OnRemoteDied(const wptr &object) override; +// }; class InputMethodController : public RefBase { public: static sptr GetInstance(); - void Attach(sptr &listener); - std::u16string GetTextBeforeCursor(int32_t number); - std::u16string GetTextAfterCursor(int32_t number); - void ShowTextInput(); - void HideTextInput(); - void Close(); - void OnRemoteSaDied(const wptr &object); - void OnCursorUpdate(CursorInfo cursorInfo); - void OnSelectionChange(std::u16string text, int start, int end); - void OnConfigurationChange(Configuration info); - bool dispatchKeyEvent(std::shared_ptr keyEvent); - void DisplayOptionalInputMethod(); - std::vector ListInputMethod(); - int32_t GetEnterKeyType(); - int32_t GetInputPattern(); - void HideCurrentInput(); - void SetCallingWindow(uint32_t windowId); - int32_t SwitchInputMethod(InputMethodProperty *target); +// void Attach(sptr &listener); +// std::u16string GetTextBeforeCursor(int32_t number); +// std::u16string GetTextAfterCursor(int32_t number); +// void ShowTextInput(); +// void HideTextInput(); +// void Close(); +// void OnRemoteSaDied(const wptr &object); +// void OnCursorUpdate(CursorInfo cursorInfo); +// void OnSelectionChange(std::u16string text, int start, int end); +// void OnConfigurationChange(Configuration info); +// bool dispatchKeyEvent(std::shared_ptr keyEvent); +// void DisplayOptionalInputMethod(); +// std::vector ListInputMethod(); +// int32_t GetEnterKeyType(); +// int32_t GetInputPattern(); +// void HideCurrentInput(); +// void SetCallingWindow(uint32_t windowId); +// int32_t SwitchInputMethod(InputMethodProperty *target); + std::shared_ptr GetCurrentInputMethod(); private: - InputMethodController(); - ~InputMethodController(); - - bool Initialize(); - sptr GetImsaProxy(); - void PrepareInput(int32_t displayId, sptr &client, sptr &channel, - InputAttribute &attribute); - void StartInput(sptr &client); - void StopInput(sptr &client); - void ReleaseInput(sptr &client); - void WorkThread(); + InputMethodController() = default; + ~InputMethodController() override = default; - sptr mInputDataChannel; - sptr mClient; - sptr mImms; - sptr deathRecipient_; - sptr mAgent; - sptr textListener; - InputAttribute mAttribute; - std::u16string mTextString; - int mSelectOldBegin = 0; - int mSelectOldEnd = 0; - int mSelectNewBegin = 0; - int mSelectNewEnd = 0; - CursorInfo cursorInfo_; +// bool Initialize(); +// sptr GetImsaProxy(); +// void PrepareInput(int32_t displayId, sptr &client, sptr &channel, +// InputAttribute &attribute); +// void StartInput(sptr &client); +// void StopInput(sptr &client); +// void ReleaseInput(sptr &client); +// void WorkThread(); - static std::mutex instanceLock_; - static sptr instance_; - std::thread workThreadHandler; - MessageHandler *msgHandler; - bool stop_; - int32_t enterKeyType_ = 0; - int32_t inputPattern_ = 0; +// sptr mInputDataChannel; +// sptr mClient; +// sptr mImms; +// sptr deathRecipient_; +// sptr mAgent; +// sptr textListener; +// InputAttribute mAttribute; +// std::u16string mTextString; +// int mSelectOldBegin = 0; +// int mSelectOldEnd = 0; +// int mSelectNewBegin = 0; +// int mSelectNewEnd = 0; +// CursorInfo cursorInfo_; +// +// static std::mutex instanceLock_; +// static sptr instance_; +// std::thread workThreadHandler; +// MessageHandler *msgHandler; +// bool stop_; +// int32_t enterKeyType_ = 0; +// int32_t inputPattern_ = 0; }; -} // namespace MiscServices + std::shared_ptr InputMethodController::GetCurrentInputMethod() + { + return std::shared_ptr(); + } + sptr InputMethodController::GetInstance() + { + static InputMethodController inputMethodController; + return &inputMethodController; + } + } // namespace MiscServices } // namespace OHOS #endif // FRAMEWORKS_INPUTMETHOD_CONTROLLER_INCLUDE_INPUT_METHOD_CONTROLLER_H diff --git a/mock/innerkits/inputmethod_native/inputmethod_client/include/input_method_property.h b/mock/innerkits/inputmethod_native/inputmethod_client/include/input_method_property.h new file mode 100644 index 00000000..733c4329 --- /dev/null +++ b/mock/innerkits/inputmethod_native/inputmethod_client/include/input_method_property.h @@ -0,0 +1,47 @@ +/* +* Copyright (C) 2022 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include +#include + +#ifndef INPUTMETHOD_IMF_INPUT_METHOD_PROPERTY_H +#define INPUTMETHOD_IMF_INPUT_METHOD_PROPERTY_H + +namespace OHOS { +namespace MiscServices { +struct Property { + std::string name; // the bundleName of inputMethod + std::string id; // the extensionName of inputMethod + std::string label; // the label of inputMethod + int32_t labelId = 0; // the labelId of inputMethod + std::string icon; // the icon of inputMethod + int32_t iconId = 0; // the icon id of inputMethod +}; + +struct SubProperty { + std::string label; // the label of subtype + int32_t labelId = 0; // the labelId of subtype + std::string name; // the bundleName of inputMethod + std::string id; // the name of subtype + std::string mode; // the mode of subtype, containing "upper" and "lower" + std::string locale; // the tongues of subtype, such as "zh_CN", "en_US", etc. + std::string language; // the language of subtype + std::string icon; // the icon of subtype + int32_t iconId = 0; // the icon id of subtype +}; +} // namespace MiscServices +} // namespace OHOS + +#endif // INPUTMETHOD_IMF_INPUT_METHOD_PROPERTY_H diff --git a/mock/innerkits/inputmethod_native/inputmethod_client/include/input_method_system_ability_proxy.h b/mock/innerkits/inputmethod_native/inputmethod_client/include/input_method_system_ability_proxy.h index 3ef09730..034e4627 100644 --- a/mock/innerkits/inputmethod_native/inputmethod_client/include/input_method_system_ability_proxy.h +++ b/mock/innerkits/inputmethod_native/inputmethod_client/include/input_method_system_ability_proxy.h @@ -36,12 +36,12 @@ namespace MiscServices { ~InputMethodSystemAbilityProxy() = default; DISALLOW_COPY_AND_MOVE(InputMethodSystemAbilityProxy); - void prepareInput(MessageParcel& data) override; - void releaseInput(MessageParcel& data) override; - void startInput(MessageParcel& data) override; - void stopInput(MessageParcel& data) override; - void SetCoreAndAgent(MessageParcel& data) override; - void HideCurrentInput(MessageParcel& data) override; +// void prepareInput(MessageParcel& data) override; +// void releaseInput(MessageParcel& data) override; +// void startInput(MessageParcel& data) override; +// void stopInput(MessageParcel& data) override; +// void SetCoreAndAgent(MessageParcel& data) override; +// void HideCurrentInput(MessageParcel& data) override; int32_t Prepare(int32_t displayId, sptr &client, sptr &channel, InputAttribute &attribute); @@ -49,17 +49,17 @@ namespace MiscServices { int32_t Start(sptr &client); int32_t Stop(sptr &client); - void displayOptionalInputMethod(MessageParcel& data) override; - int32_t getDisplayMode(int32_t &retMode) override; - int32_t getKeyboardWindowHeight(int32_t &retHeight) override; - int32_t getCurrentKeyboardType(KeyboardType *retType) override; - int32_t listInputMethodEnabled(std::vector *properties) override; - int32_t listInputMethod(std::vector *properties) override; - int32_t listKeyboardType(const std::u16string& imeId, std::vector *types) override; - int32_t SwitchInputMethod(InputMethodProperty* target); +// void displayOptionalInputMethod(MessageParcel& data) override; +// int32_t getDisplayMode(int32_t &retMode) override; +// int32_t getKeyboardWindowHeight(int32_t &retHeight) override; +// int32_t getCurrentKeyboardType(KeyboardType *retType) override; +// int32_t listInputMethodEnabled(std::vector *properties) override; +// int32_t listInputMethod(std::vector *properties) override; +// int32_t listKeyboardType(const std::u16string& imeId, std::vector *types) override; +// int32_t SwitchInputMethod(InputMethodProperty* target); private: - static inline BrokerDelegator delegator_; +// static inline BrokerDelegator delegator_; }; } // namespace MiscServices } // namespace OHOS diff --git a/mock/innerkits/multimedia_image_standard/image_native/include/pixel_map.h b/mock/innerkits/multimedia_image_standard/image_native/include/pixel_map.h index 1ae84012..d3d2e676 100644 --- a/mock/innerkits/multimedia_image_standard/image_native/include/pixel_map.h +++ b/mock/innerkits/multimedia_image_standard/image_native/include/pixel_map.h @@ -104,7 +104,8 @@ public: NATIVEEXPORT void FreePixelMap(); NATIVEEXPORT AllocatorType GetAllocatorType(); NATIVEEXPORT void *GetFd() const; - + NATIVEEXPORT static PixelMap *DecodeTlv(std::vector &buff); + NATIVEEXPORT virtual bool EncodeTlv(std::vector &buff) const; NATIVEEXPORT uint32_t GetCapacity() { return pixelsSize_; diff --git a/mock/innerkits/samgr_standard/samgr_proxy/include/system_ability_load_callback_stub.h b/mock/innerkits/samgr_standard/samgr_proxy/include/system_ability_load_callback_stub.h index 9bf201f1..6e022ed9 100644 --- a/mock/innerkits/samgr_standard/samgr_proxy/include/system_ability_load_callback_stub.h +++ b/mock/innerkits/samgr_standard/samgr_proxy/include/system_ability_load_callback_stub.h @@ -22,8 +22,12 @@ namespace OHOS { class SystemAbilityLoadCallbackStub : public IRemoteStub { public: - int32_t OnRemoteRequest(uint32_t code, MessageParcel& data, MessageParcel& reply, MessageOption& option) override; - +// int32_t OnRemoteRequest(uint32_t code, MessageParcel& data, MessageParcel& reply, MessageOption& option) override; + int32_t OnRemoteRequest(uint32_t code, MessageParcel& data, MessageParcel& reply, + MessageOption& option) + { + return IPCObjectStub::OnRemoteRequest(code, data, reply, option); + } private: static bool CheckInputSystemAbilityId(int32_t systemAbilityId); static bool EnforceInterceToken(MessageParcel& data); diff --git a/mock/innerkits/startup_l2/syspara/include/parameter.h b/mock/innerkits/startup_l2/syspara/include/parameter.h index f4ddf041..9f044e53 100644 --- a/mock/innerkits/startup_l2/syspara/include/parameter.h +++ b/mock/innerkits/startup_l2/syspara/include/parameter.h @@ -40,7 +40,7 @@ extern "C" { * @since 1 * @version 1 */ -int GetParameter(const char *key, const char *def, char *value, unsigned int len); +static int GetParameter(const char *key, const char *def, char *value, unsigned int len) { return 0; }; /** * @brief Sets or updates a system parameter. @@ -57,7 +57,7 @@ int GetParameter(const char *key, const char *def, char *value, unsigned int len * @since 1 * @version 1 */ -int SetParameter(const char *key, const char *value); +static int SetParameter(const char *key, const char *value) { return 0; }; /** * @brief Wait for a system parameter with specified value. @@ -95,7 +95,7 @@ int WaitParameter(const char *key, const char *value, int timeout); * @version 1.1 */ typedef void (*ParameterChgPtr)(const char *key, const char *value, void *context); -int WatchParameter(const char *keyprefix, ParameterChgPtr callback, void *context); +static int WatchParameter(const char *keyprefix, ParameterChgPtr callback, void *context) { return 0; }; long long GetSystemCommitId(void); diff --git a/mock/innerkits/time_native/time_service/include/time_service_client.h b/mock/innerkits/time_native/time_service/include/time_service_client.h index 94c97193..4d526725 100644 --- a/mock/innerkits/time_native/time_service/include/time_service_client.h +++ b/mock/innerkits/time_native/time_service/include/time_service_client.h @@ -19,9 +19,9 @@ #include #include "refbase.h" -#include "time_service_interface.h" +//#include "time_service_interface.h" #include "iremote_object.h" -#include "timer_call_back.h" +//#include "timer_call_back.h" namespace OHOS { namespace MiscServices { @@ -68,21 +68,27 @@ public: * @descpriton get the wall time(the UTC time from 1970 0H:0M:0S) in milliseconds * @return int64_t, milliseconds in wall time, ret < 0 on failed. */ - int64_t GetWallTimeMs(); + int64_t GetWallTimeMs() { + return 0; + }; /** * GetWallTimeNs * @descpriton get the wall time(the UTC time from 1970 0H:0M:0S) in nanoseconds * @return int64_t, nanoseconds in wall time, ret < 0 on failed. */ - int64_t GetWallTimeNs(); + int64_t GetWallTimeNs() { + return 0; + }; /** * GetBootTimeMs * @descpriton get the time since boot(include time spent in sleep) in milliseconds. * @return int64_t, milliseconds in boot time, ret < 0 on failed. */ - int64_t GetBootTimeMs(); + int64_t GetBootTimeMs() { + return 0; + }; /** * GetBootTimeNs @@ -119,12 +125,12 @@ public: */ int64_t GetThreadTimeNs(); - /** - * CreateTimer - * @param TimerInfo timer info - * @return uint64_t > 0 on success, == 0 failure. - */ - uint64_t CreateTimer(std::shared_ptr TimerInfo); +// /** +// * CreateTimer +// * @param TimerInfo timer info +// * @return uint64_t > 0 on success, == 0 failure. +// */ +// uint64_t CreateTimer(std::shared_ptr TimerInfo); /** * StartTimer @@ -180,13 +186,18 @@ public: private: TimeServiceClient(); ~TimeServiceClient(); - static sptr ConnectService(); +// static sptr ConnectService(); static std::mutex instanceLock_; static sptr instance_; - static sptr timeServiceProxy_; +// static sptr timeServiceProxy_; static sptr deathRecipient_; }; + +sptr TimeServiceClient::GetInstance() +{ + return sptr(); +} } // MiscServices } // OHOS #endif // SERVICES_INCLUDE_TIME_SERVICES_MANAGER_H \ No newline at end of file diff --git a/mock/innerkits/window_manager/libwm/include/window_manager.h b/mock/innerkits/window_manager/libwm/include/window_manager.h index 09aae692..5a71a3c2 100644 --- a/mock/innerkits/window_manager/libwm/include/window_manager.h +++ b/mock/innerkits/window_manager/libwm/include/window_manager.h @@ -53,6 +53,14 @@ public: WindowType windowType_ = WindowType::WINDOW_TYPE_APP_MAIN_WINDOW; sptr abilityToken_; }; +bool FocusChangeInfo::Marshalling(Parcel& parcel) const +{ + return false; +} +FocusChangeInfo* FocusChangeInfo::Unmarshalling(Parcel& parcel) +{ + return nullptr; +} class IFocusChangedListener : virtual public RefBase { public: @@ -134,35 +142,44 @@ class WindowManager { WM_DECLARE_SINGLE_INSTANCE_BASE(WindowManager); friend class WindowManagerAgent; public: - void RegisterFocusChangedListener(const sptr& listener); - void UnregisterFocusChangedListener(const sptr& listener); - void RegisterSystemBarChangedListener(const sptr& listener); - void UnregisterSystemBarChangedListener(const sptr& listener); - void RegisterWindowUpdateListener(const sptr& listener); - void UnregisterWindowUpdateListener(const sptr& listener); - void RegisterVisibilityChangedListener(const sptr& listener); - void UnregisterVisibilityChangedListener(const sptr& listener); - void RegisterCameraFloatWindowChangedListener(const sptr& listener); - void UnregisterCameraFloatWindowChangedListener(const sptr& listener); - void MinimizeAllAppWindows(DisplayId displayId); - WMError ToggleShownStateForAllAppWindows(); - WMError SetWindowLayoutMode(WindowLayoutMode mode); - WMError GetAccessibilityWindowInfo(sptr& windowInfo) const; +// void RegisterFocusChangedListener(const sptr& listener); +// void UnregisterFocusChangedListener(const sptr& listener); +// void RegisterSystemBarChangedListener(const sptr& listener); +// void UnregisterSystemBarChangedListener(const sptr& listener); +// void RegisterWindowUpdateListener(const sptr& listener); +// void UnregisterWindowUpdateListener(const sptr& listener); +// void RegisterVisibilityChangedListener(const sptr& listener); +// void UnregisterVisibilityChangedListener(const sptr& listener); +// void RegisterCameraFloatWindowChangedListener(const sptr& listener); +// void UnregisterCameraFloatWindowChangedListener(const sptr& listener); +// void MinimizeAllAppWindows(DisplayId displayId); +// WMError ToggleShownStateForAllAppWindows(); +// WMError SetWindowLayoutMode(WindowLayoutMode mode); +// WMError GetAccessibilityWindowInfo(sptr& windowInfo) const; + void GetFocusWindowInfo(FocusChangeInfo& focusInfo); private: WindowManager(); ~WindowManager() = default; - class Impl; - std::unique_ptr pImpl_; - - void UpdateFocusStatus(uint32_t windowId, const sptr& abilityToken, WindowType windowType, - DisplayId displayId, bool focused) const; - void UpdateFocusChangeInfo(const sptr& focusChangeInfo, bool focused) const; - void UpdateSystemBarRegionTints(DisplayId displayId, const SystemBarRegionTints& tints) const; - void NotifyAccessibilityWindowInfo(const sptr& windowInfo, WindowUpdateType type) const; - void UpdateWindowVisibilityInfo( - const std::vector>& windowVisibilityInfos) const; - void UpdateCameraFloatWindowStatus(uint32_t accessTokenId, bool isShowing) const; +// class Impl; +// std::unique_ptr pImpl_; +// +// void UpdateFocusStatus(uint32_t windowId, const sptr& abilityToken, WindowType windowType, +// DisplayId displayId, bool focused) const; +// void UpdateFocusChangeInfo(const sptr& focusChangeInfo, bool focused) const; +// void UpdateSystemBarRegionTints(DisplayId displayId, const SystemBarRegionTints& tints) const; +// void NotifyAccessibilityWindowInfo(const sptr& windowInfo, WindowUpdateType type) const; +// void UpdateWindowVisibilityInfo( +// const std::vector>& windowVisibilityInfos) const; +// void UpdateCameraFloatWindowStatus(uint32_t accessTokenId, bool isShowing) const; +}; +void WindowManager::GetFocusWindowInfo(FocusChangeInfo& focusInfo) {} +WindowManager& WindowManager::GetInstance() { + static WindowManager windowManager; + return windowManager; +} +WindowManager::WindowManager(){ + }; } // namespace Rosen } // namespace OHOS diff --git a/mock/innerkits/window_manager/libwm/include/wm_single_instance.h b/mock/innerkits/window_manager/libwm/include/wm_single_instance.h new file mode 100644 index 00000000..3442fdeb --- /dev/null +++ b/mock/innerkits/window_manager/libwm/include/wm_single_instance.h @@ -0,0 +1,43 @@ +/* +* Copyright (c) 2021-2022 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef OHOS_WM_SINGLE_INSTANCE_H +#define OHOS_WM_SINGLE_INSTANCE_H +namespace OHOS { +namespace Rosen { +#define WM_DECLARE_SINGLE_INSTANCE_BASE(className) \ +public: \ + static className& GetInstance(); \ + className(const className&) = delete; \ + className& operator= (const className&) = delete; \ + className(className&&) = delete; \ + className& operator= (className&&) = delete; \ + +#define WM_DECLARE_SINGLE_INSTANCE(className) \ + WM_DECLARE_SINGLE_INSTANCE_BASE(className) \ +protected: \ + className() = default; \ + virtual ~className() = default; \ + +#define WM_IMPLEMENT_SINGLE_INSTANCE(className) \ +className& className::GetInstance() \ +{ \ + static className instance; \ + return instance; \ +} \ + +} // namespace OHOS +} +#endif // OHOS_SINGLE_INSTANCE_H diff --git a/mock/src/distributed_file_daemon_manager.cpp b/mock/src/distributed_file_daemon_manager.cpp new file mode 100644 index 00000000..d731d565 --- /dev/null +++ b/mock/src/distributed_file_daemon_manager.cpp @@ -0,0 +1,27 @@ +// +// Created by wangh on 2024/3/23. +// + +#include "distributed_file_daemon_manager.h" + +namespace OHOS { +namespace Storage { +DistributedFile::DistributedFileDaemonManager& +DistributedFile::DistributedFileDaemonManager::GetInstance() +{ + static DistributedFile::DistributedFileDaemonManager instance; + return instance; +} +int32_t DistributedFile::DistributedFileDaemonManager::OpenP2PConnection( + const DistributedHardware::DmDeviceInfo& deviceInfo) +{ + return 0; +} +int32_t DistributedFile::DistributedFileDaemonManager::CloseP2PConnection( + const DistributedHardware::DmDeviceInfo& deviceInfo) +{ + return 0; +} +} +}; // namespace OHOS + diff --git a/mock/src/mock_aa_fwk.cpp b/mock/src/mock_aa_fwk.cpp index 117f349c..d46764ca 100644 --- a/mock/src/mock_aa_fwk.cpp +++ b/mock/src/mock_aa_fwk.cpp @@ -192,6 +192,7 @@ ErrCode AbilityManagerClient::DumpAbilityInfoDone(std::vector &info sptr AbilityManagerClient::GetAbilityManager() { return sptr(); } void AbilityManagerClient::ResetProxy(const wptr &remote) {} void AbilityManagerClient::HandleDlpApp(Want &want) {} +ErrCode AbilityManagerClient::CheckUIExtensionIsFocused(uint32_t uiExtensionTokenId, bool& isFocused) { return 0; } AbilityConnectionStub::AbilityConnectionStub() {} AbilityConnectionStub::~AbilityConnectionStub() {} int AbilityConnectionStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, diff --git a/mock/src/mock_image..cpp b/mock/src/mock_image..cpp index 5fda61b4..7466c27b 100644 --- a/mock/src/mock_image..cpp +++ b/mock/src/mock_image..cpp @@ -229,4 +229,12 @@ void *PixelMap::GetFd() const { return nullptr; } +PixelMap* PixelMap::DecodeTlv(std::vector& buff) +{ + return nullptr; +} +bool PixelMap::EncodeTlv(std::vector& buff) const +{ + return true; +} } \ No newline at end of file diff --git a/mock/src/mock_napi_base_context.cpp b/mock/src/mock_napi_base_context.cpp index 770e6e40..0d568b56 100644 --- a/mock/src/mock_napi_base_context.cpp +++ b/mock/src/mock_napi_base_context.cpp @@ -29,6 +29,7 @@ std::shared_ptr GetStageModeContext(napi_env env, napi_value object) } namespace OHOS::AppExecFwk { napi_value WrapWantParams(napi_env env, const AAFwk::WantParams &wantParams) { return nullptr; }; +bool UnwrapWantParams(napi_env env, napi_value param, AAFwk::WantParams &wantParams) { return true; } napi_value WrapWant(napi_env env, const Want &want) { return nullptr; } bool UnwrapWant(napi_env env, napi_value param, Want &want) { return false; } int UnwrapInt32FromJS(napi_env env, napi_value param, int defaultValue) { return 0; } diff --git a/mock/src/mock_notification.cpp b/mock/src/mock_notification.cpp index e2391d31..627499a5 100644 --- a/mock/src/mock_notification.cpp +++ b/mock/src/mock_notification.cpp @@ -39,6 +39,11 @@ WantParams &WantParams::operator=(const WantParams &other) params_ = other.params_; return *this; } +int WantParams::GetIntParam(const std::string& key, const int defaultValue) const { return 0; } +WantParams* WantParams::Unmarshalling(Parcel& parcel) +{ + return nullptr; +} Want::Want() {} Want::Want(OHOS::AAFwk::Want const &ref):params_(ref.params_) {} @@ -167,6 +172,11 @@ Uri Want::GetLowerCaseScheme(const Uri &uri) { return Uri("");} void Want::ToUriStringInner(std::string &uriString) const{ } nlohmann::json Want::ToJson() const { return nlohmann::json();} bool Want::ReadFromJson(nlohmann::json &wantJson) { return false;} +Want& Want::SetElementName(const std::string& bundleName, const std::string& abilityName) +{ + static Want want; + return want; +} UnsupportedData::~UnsupportedData() {} Operation::Operation() : uri_("") {} Operation::~Operation() {} diff --git a/mock/src/mock_trace.cpp b/mock/src/mock_trace.cpp index c2f3fa0e..a13e9015 100644 --- a/mock/src/mock_trace.cpp +++ b/mock/src/mock_trace.cpp @@ -22,6 +22,8 @@ void MiddleTrace(uint64_t label, const std::string& beforeValue, const std::stri void FinishTrace(uint64_t label) {}; // void FinishTrace(uint64_t label, const std::string& value) {}; void UpdateTraceLabel() {} +void StartAsyncTrace(uint64_t label, const std::string& value, int32_t taskId, float limit) {}; +void FinishAsyncTrace(uint64_t label, const std::string& value, int32_t taskId) {}; #ifdef __cplusplus } #endif diff --git a/mock/src/mock_uri_permission_manager.cpp b/mock/src/mock_uri_permission_manager.cpp index c08dce9f..922229a6 100644 --- a/mock/src/mock_uri_permission_manager.cpp +++ b/mock/src/mock_uri_permission_manager.cpp @@ -60,6 +60,11 @@ void UriPermissionManagerClient::OnLoadSystemAbilitySuccess(const sptr& uriVec, unsigned int flag, + const std::string targetBundleName, int32_t appIndex) +{ + return 0; +} void UriPermissionManagerClient::UpmsDeathRecipient::OnRemoteDied([[maybe_unused]] const wptr& remote) {} } // namespace AAFwk diff --git a/pasteboard/.gitattributes b/pasteboard/.gitattributes new file mode 100644 index 00000000..51c63e29 --- /dev/null +++ b/pasteboard/.gitattributes @@ -0,0 +1,15 @@ +*.tgz filter=lfs diff=lfs merge=lfs -text +*.trp filter=lfs diff=lfs merge=lfs -text +*.apk filter=lfs diff=lfs merge=lfs -text +*.jar filter=lfs diff=lfs merge=lfs -text +*.mp4 filter=lfs diff=lfs merge=lfs -text +*.zip filter=lfs diff=lfs merge=lfs -text +*.asm filter=lfs diff=lfs merge=lfs -text +*.8svn filter=lfs diff=lfs merge=lfs -text +*.9svn filter=lfs diff=lfs merge=lfs -text +*.dylib filter=lfs diff=lfs merge=lfs -text +*.exe filter=lfs diff=lfs merge=lfs -text +*.a filter=lfs diff=lfs merge=lfs -text +*.so filter=lfs diff=lfs merge=lfs -text +*.bin filter=lfs diff=lfs merge=lfs -text +*.dll filter=lfs diff=lfs merge=lfs -text diff --git a/pasteboard/.gitignore b/pasteboard/.gitignore new file mode 100644 index 00000000..0a955085 --- /dev/null +++ b/pasteboard/.gitignore @@ -0,0 +1,2 @@ +.idea/ +.vscode/ \ No newline at end of file diff --git a/pasteboard/BUILD.gn b/pasteboard/BUILD.gn new file mode 100644 index 00000000..27ec732d --- /dev/null +++ b/pasteboard/BUILD.gn @@ -0,0 +1,29 @@ +# Copyright (C) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") + +################################################################################ + +group("pasteboard_packages") { + if (is_standard_system) { + deps = [ + "etc/init:pasteboardservice.cfg", + "framework/framework:build_module", + "framework/innerkits:pasteboard_client", + "interfaces/kits:pasteboard_napi", + "profile:distributeddatamgr_pasteboard_sa_profiles", + "services:pasteboard_service", + ] + } +} diff --git a/pasteboard/CMakeLists.txt b/pasteboard/CMakeLists.txt new file mode 100644 index 00000000..dd7525b5 --- /dev/null +++ b/pasteboard/CMakeLists.txt @@ -0,0 +1,69 @@ +cmake_minimum_required(VERSION 3.10.2) +project(pasteboard) +#add_subdirectory(pasteboardService) +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++1y -fno-rtti -fvisibility=default -D_GNU_SOURCE") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdata-sections -fPIC -fpic -ffunction-sections -D_GLIBC_MOCK") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wl,--no-as-needed -ldl") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wformat=0") + +set(MOCK_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../mock) +set(KV_STORE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../kv_store) + +add_definitions(-DPB_DEVICE_MANAGER_ENABLE -DNAPI_EXPERIMENTAL) +# 设置名为pasteboardSrc的源代码目录 +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/framework/framework/clip pasteboardSrc) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/framework/framework/device pasteboardSrc) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/framework/framework/serializable pasteboardSrc) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/framework/innerkits pasteboardSrc) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/framework/innerkits/src pasteboardSrc) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/framework/tlv pasteboardSrc) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/framework/uri pasteboardSrc) + +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/interfaces/kits/napi/src pasteboardSrc) + +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/services/account/src pasteboardSrc) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/services/core/src pasteboardSrc) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/services/dfx/src pasteboardSrc) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/services/dfx/src/behaviour pasteboardSrc) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/services/dfx/src/fault pasteboardSrc) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/services/dfx/src/statistic pasteboardSrc) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/services/load/src pasteboardSrc) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/services/zidl/src pasteboardSrc) + +#包含的头文件 +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/framework/framework/clip) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/framework/framework/include) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/framework/framework/include/device) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/framework/innerkits/include) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/framework/tlv) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/framework/uri) + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/interfaces/kits/napi/include) + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/services/account/include) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/services/core/include) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/services/dfx/src) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/services/dfx/src/behaviour) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/services/dfx/src/fault) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/services/dfx/src/statistic) + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/services/load/include) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/services/zidl/include) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/utils/native/include) + +include(${MOCK_DIR}/include/CMakeLists.txt OPTIONAL) +include(${KV_STORE_DIR}/interfaces/CMakeLists.txt OPTIONAL) + + +# 创建一个名为pasteboard的共享库,源代码路径是${pasteboardSrc} +add_library(pasteboard SHARED ${pasteboardSrc}) + +# 对外暴露的头文件,Public表示我依赖,外部依赖本so以后也可以直接引头文件,private表示不能 +target_include_directories(pasteboard PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/kits/napi/include) +target_include_directories(pasteboard PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/framework/innerkits/include) + +# 前者依赖后者,后边有多个时表示第一个依赖后边所有的 +set(links secure mock) +target_link_libraries(pasteboard ${links}) + diff --git a/pasteboard/CODEOWNERS b/pasteboard/CODEOWNERS new file mode 100644 index 00000000..48318025 --- /dev/null +++ b/pasteboard/CODEOWNERS @@ -0,0 +1,15 @@ +# Copyright (C) 2023 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# any changes to services/core/include/pasteboard_serv_ipc_interface_code.h needs to be reviewed by @leonchan5 +services/core/include/pasteboard_serv_ipc_interface_code.h @leonchan5 \ No newline at end of file diff --git a/pasteboard/LICENSE b/pasteboard/LICENSE new file mode 100644 index 00000000..4947287f --- /dev/null +++ b/pasteboard/LICENSE @@ -0,0 +1,177 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS \ No newline at end of file diff --git a/pasteboard/OAT.xml b/pasteboard/OAT.xml new file mode 100644 index 00000000..653f0599 --- /dev/null +++ b/pasteboard/OAT.xml @@ -0,0 +1,73 @@ + + + + + + LICENSE + + + + + + + + + + + + + \ No newline at end of file diff --git a/pasteboard/README.md b/pasteboard/README.md new file mode 100644 index 00000000..17b364c8 --- /dev/null +++ b/pasteboard/README.md @@ -0,0 +1,419 @@ +# pasteBoardService + +## Introduction + +​ As a functional component of the stray subsystem, the clipboard service provides the ability to manage the system clipboard and supports the system copy and paste functions. The system clipboard supports package text, hypertext, URIs and other content operations. + +**picture 1** Subsystem Architecture Diagram +![](figures/subsystem_architecture.png "Subsystem architecture") + +​ The clipboard service provides functions that support application developers to use clipboard-related services conveniently and efficiently. Its main components include clipboard management client and clipboard service. The clipboard management client is responsible for clipboard interface management, providing clipboard northbound JS API to applications; creating clipboard data on the application framework side, requesting clipboard SA to perform clipboard creation, deletion, query, text conversion, configuration, etc. The clipboard service is responsible for clipboard event management, manages the life cycle of clipboard SA (startup, destruction, multi-user, etc.); executes application requests, notifies clipboard data management, and returns the results to the clipboard management client. + + + +## Directory Structure + +``` +/foundation/distributeddatamgr/pasteboard +├── etc # Configuration files for the processes contained in the component +├── figures # Framework diagram +├── framework # innerKit interface +├── interfaces # The interface code provided by the component externally +│ └── kits # Interface provided to the application +├── profile # Configuration files for system services contained in the component +├── services # clipboard service implementation +│ └── core # Core code implementation +│ └── test # native test code +│ └── zidl # Cross-process communication code implementation +├── utils # Tests or services use mocked data +└──README.md # Instructions for use +``` + +## illustrate + +### Interface Description + +**list 1** PasteBoard open main method + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

interface name

+

describe

+

createHtmlData(htmlText: string): PasteData;

+

Create a PasteData object of type MIMETYPE_TEXT_HTML for HTML type data

+

createWantData(want: Want): PasteData;

+

Create a PasteData object of type MIMETYPE_TEXT_WANT for data of type want

+

createPlainTextData(text: string): PasteData

+

Create a PasteData object of type MIMETYPE_TEXT_PLAIN for plain text data

+

createUriData(uri: string): PasteData;

+

Create a PasteData object of type MIMETYPE_TEXT_URI for data of type URI

+

createHtmlTextRecord(htmlText: string): PasteDataRecord;

+

Create a PasteDataRecord object of type RecordMIMETYPE_TEXT_HTML for hypertext type data

+

createWantRecord(want: Want): PasteDataRecord;

+

Create a PasteDataRecord object of type MIMETYPE_TEXT_WANT for data of type want

+

createPlainTextRecord(text: string): PasteDataRecord;

+

Create a PasteDataRecord object of type MIMETYPE_TEXT_PLAIN for plain text data

+

createUriRecord(uri: string): PasteDataRecord;

+

Create a PasteDataRecord object of type MIMETYPE_TEXT_URI for data of type URI

+

getSystemPasteboard(): SystemPasteboard

+

Get system clipboard

+
+ + + +**list 2** SystemPasteboard open main method + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

interface name

+

describe

+

on(type:'update', callback: () => void): void;

+

Callback called when the open pasteboard content changes

+

off(type: 'update', callback?: () => void): void

+

Callback called when the content of the pasteboard is closed

+

clear(callback: AsyncCallback): void

+

clear clipboard

+

clear(): Promise;

+

clear clipboard

+

getPasteData(callback: AsyncCallback<PasteData>): void

+

Get system clipboard data object

+

getPasteData():Promise<PasteData>

+

Get system clipboard data object

+

hasPasteData(callback: AsyncCallback<boolean>:void;

+

Check if there is content in the pasteboard

+

hasPasteData(): Promise<boolean>

+

Check if there is content in the pasteboard

+

setPasteData(data: PasteData, callback: AsyncCallback<void>:void;

+

Write PasteData to the pasteboard

+

setPasteData(data: PasteData): Promise<void>

+

Write PasteData to the pasteboard

+
+ + + +**list 3** PasteData open main method + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

interface name

+

describe

+

addHtmlRecord(htmlText: string): void;

+

Add the HTML text record to the PasteData object and update the MIME type to PasteData#MIMETYPE_TEXT_HTML in the DataProperty.

+

addWantRecord(want: Want): void;

+

Add want record to PasteData object and update MIME type to PasteData#MIMETYPE_TEXT_WANT in DataProperty

+

addRecord(record: PasteDataRecord): void;

+

Add PasteRecord to paste data object and update MIME type in data attribute

+

addTextRecord(text: string): void;;

+

Add plain text records to PasteData object and update MIME type to PasteData#MIMETYPE_TEXT_PLAIN in DataProperty

+

addUriRecord(uri: string): void;

+

Add URI record to PasteData object and update MIME type to PasteData#MIMETYPE_TEXT_URI in DataProperty

+

getMimeTypes(): Array<string>

+

MIME type of everything on the pasteboard

+

getPrimaryHtml(): string;

+

HTML text of the main record in the PasteData object

+

getPrimaryWant(): Want;

+

The want of the main record in the PasteData object

+

getPrimaryMimeType(): string;

+

The MIME type of the main record in the PasteData object

+

getPrimaryUri(): string;

+

URI of the main record in the PasteData object

+

getProperty(): PasteDataProperty;

+

Get the properties of the clipboard data object

+

getRecordAt(index: number): PasteDataRecord;

+

records based on the specified index

+

getRecordCount(): number;

+

Number of records in PasteData object

+

hasMimeType(mimeType: string): boolean;

+

Checks if data of the specified MIME type exists in the DataProperty

+

removeRecordAt(index: number): boolean;

+

Delete records based on specified index

+

replaceRecordAt(index: number, record: PasteDataRecord): boolean;

+

Replace the specified record with a new record

+
+ + + + + +**list 4** PasteDataRecord open main method + + + + + + + + + + + + +

interface name

+

describe

+

convertToText(callback: AsyncCallback<string>): void;

+

Convert PasteData to text content

+

convertToText(): Promise<void>

+

Convert PasteData to text content

+
+ + + +**list 5** PasteDataProperty Parameter Description + + + + + + + + + + + + + + + + + + + + + + + + + + + +

name

+

type

+

illustrate

+

additions{[key:string]}

+

object

+

Additional property data key-value pair

+

mimeTypes

+

Array

+

Distinct MIME types for all records in PasteData

+

tag

+

string

+

User-defined labels for PasteData objects

+

timestamp

+

number

+

Timestamp indicating when the data was written to the system clipboard.

+

localOnly

+

boolean

+

Check if PasteData is set for local access only.

+
+ + +### Instructions for use + +Clipboard module usage example: + +``` +// import module +import pasteboard from '@ohos.pasteboard' +//text copy +console.log('Get SystemPasteboard') +var systemPasteboard = pasteboard.getSystemPasteboard() +systemPasteboard.clear() + +var textData = 'Hello World!' +console.log('createPlainTextData = ' + textData) +var pasteData = pasteboard.createPlainTextData(textData) + +console.log('Writes PasteData to the pasteboard') +systemPasteboard.setPasteData(pasteData) + +console.log('Checks there is content in the pasteboard') +assert.equal(systemPasteboard.hasPasteData(), true) + +console.log('Checks the number of records') +pasteData = systemPasteboard.getPasteData() +assert.equal(pasteData.getRecordCount(), 1) + +console.log('Checks the pasteboard content') +assert.equal(pasteData.getPrimaryText(), textData) + +console.log('Checks there is a MIMETYPE_TEXT_PLAIN MIME type of data') +assert.equal(pasteData.hasMimeType(MIMETYPE_TEXT_PLAIN), true) +assert.equal(pasteData.getPrimaryMimeType(), MIMETYPE_TEXT_PLAIN) + +//clipboard change listener +console.log('Off the content changes') +var systemPasteboard = pasteboard.getSystemPasteboard() +systemPasteboard.off(contentChanges) +systemPasteboard.clear() + +var textData = 'Hello World!' +console.log('createUriData = ' + textData) +var pasteData = pasteboard.createUriData(textData) + +console.log('Writes PasteData to the pasteboard') +systemPasteboard.setPasteData(pasteData) + +console.log('Checks there is content in the pasteboard') +assert.equal(systemPasteboard.hasPasteData(), true) + +console.log('Checks the number of records') +pasteData = systemPasteboard.getPasteData() +assert.equal(pasteData.getRecordCount(), 1) + +console.log('On the content changes') +systemPasteboard.on(contentChanges) + +console.log('Removes the Record') +assert.equal(pasteData.removeRecordAt(0), true) + +console.log('Writes PasteData to the pasteboard') +systemPasteboard.setPasteData(pasteData) + +console.log('Checks the number of records') +pasteData = systemPasteboard.getPasteData() +assert.equal(pasteData.getRecordCount(), 0) + +console.log('Checks there is no content in the pasteboard') +assert.equal(systemPasteboard.hasPasteData(), false) + +var textDataNew = 'Hello World!-New' +console.log('createUriData = ' + textDataNew) +var pasteData = pasteboard.createUriData(textDataNew) + +console.log('Writes PasteData to the pasteboard') +systemPasteboard.setPasteData(pasteData) + +console.log('Checks there is content in the pasteboard') +assert.equal(systemPasteboard.hasPasteData(), true) + +console.log('Checks the number of records') +pasteData = systemPasteboard.getPasteData() +assert.equal(pasteData.getRecordCount(), 1) + +console.log('Checks the pasteboard content') +assert.equal(pasteData.getRecordAt(0).plainText, textDataNew) + +``` + + + +## Related warehouse + +**Distributed Data Management subsystem** + +[distributeddatamgr\_pasteboard](https://gitee.com/openharmony/distributeddatamgr_pasteboard) + diff --git a/pasteboard/README_ZH.md b/pasteboard/README_ZH.md new file mode 100644 index 00000000..0d91abd7 --- /dev/null +++ b/pasteboard/README_ZH.md @@ -0,0 +1,768 @@ +# 剪贴板服务 + +## 简介 + +剪贴板服务作为杂散子系统的功能组件,提供管理系统剪贴板的能力,为系统复制、粘贴功能提供支持。系统剪切板支持包文本、超本文、URIs等内容操作。 + +**图 1** 子系统架构图 +![](figures/subsystem_architecture_zh.png "子系统架构图") + +剪贴板服务,提供支撑应用开发者方便、高效的使用剪贴板相关业务的功能。其主要组件包括剪贴板管理客户端和剪贴板服务。剪贴板管理客户端负责剪贴板接口管理,提供剪贴板北向JS API给应用;在应用框架侧创建剪贴板数据、请求剪贴板SA执行剪贴板的新建、删除、查询、转换文本、配置等。剪贴板服务负责剪贴板事件管理,管理剪贴板SA的生命周期(启动、销毁、多用户等);执行应用请求,通知剪贴板数据管理,并将结果返回给剪贴板管理客户端。 + + + +## 目录 + +``` +/foundation/distributeddatamgr/pasteboard +├── etc # 组件包含的进程的配置文件 +├── figures # 构架图 +├── framework # innerKit接口 +├── interfaces # 组件对外提供的接口代码 +│ └── kits # 对应用提供的接口 +├── profile # 组件包含的系统服务的配置文件 +├── services # 剪贴板服务实现 +│ └── core # 核心代码实现 +│ └── test # native测试代码 +│ └── zidl # 跨进程通信代码实现 +├── utils # 测试或服务使用mock的数据 +└──README_zh.md # 使用说明 +``` + +## 说明 + +### 接口说明 + +**表 1** PasteBoard开放的主要方法 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

接口名

+

描述

+

createData(mimeType: string, value: ValueType): PasteData;

+

用MIME类型和值创建一个PasteData 对象

+

createRecord(mimeType: string, value: ValueType): PasteDataRecord;

+

用MIME类型和值创建一个PasteDataRecord对象

+

createHtmlData(htmlText: string): PasteData;

+

为HTML类型的数据创建一个MIMETYPE_TEXT_HTML类型的PasteData 对象

+

createWantData(want: Want): PasteData;

+

为want类型的数据创建一个MIMETYPE_TEXT_WANT类型的PasteData对象

+

createPlainTextData(text: string): PasteData;

+

为纯文本类型的数据创建一个MIMETYPE_TEXT_PLAIN类型的PasteData 对象

+

createUriData(uri: string): PasteData;

+

为URI类型的数据创建一个MIMETYPE_TEXT_URI类型的PasteData 对象

createHtmlTextRecord(htmlText: string): PasteDataRecord;

+

为超文本类型的数据创建一个RecordMIMETYPE_TEXT_HTML类型的PasteDataRecord对象

+

createWantRecord(want: Want): PasteDataRecord;

+

为want类型的数据创建一个MIMETYPE_TEXT_WANT类型的PasteDataRecord对象

+

createPlainTextRecord(text: string): PasteDataRecord;

+

为纯文本类型的数据创建一个MIMETYPE_TEXT_PLAIN类型的PasteDataRecord对象

+

createUriRecord(uri: string): PasteDataRecord;

+

为URI类型的数据创建一个MIMETYPE_TEXT_URI类型的PasteDataRecord对象

getSystemPasteboard(): SystemPasteboard;

+

获取系统剪贴板

+
+ + +**表 2** SystemPasteboard开放的主要方法 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

接口名

+

描述

+

clearData(callback: AsyncCallback<void>): void;

+

清除剪贴板

+

clearData(): Promise<void>;

+

清除剪贴板

+

getData(callback: AsyncCallback<PasteData>): void;

+

从系统剪贴板获取pastedata对象

+

getData(): Promise<PasteData>;

+

从系统剪贴板获取pastedata对象

+

hasData(callback: AsyncCallback<boolean>): void;

+

判断系统剪贴板中的内容

+

hasData(): Promise<boolean>;

+

判断系统剪贴板中的内容

+

setData(data: PasteData, callback: AsyncCallback<void>): void;

+

向系统剪贴板写入PasteData

+

setData(data: PasteData): Promise<void>;

+

向系统剪贴板写入PasteData

+

on(type:'update', callback: () => void): void;

+

打开粘贴板内容更改时调用的回调

+

off(type: 'update', callback?: () => void): void;

+

关闭粘贴板内容更改时调用的回调

+

clear(callback: AsyncCallback<void>): void;

+

清除剪贴板

+

clear(): Promise<void>;

+

清除剪贴板

+

getPasteData(callback: AsyncCallback<PasteData>): void;

+

获取系统剪贴板数据对象

+

getPasteData():Promise<PasteData>;

+

获取系统剪贴板数据对象

+

hasPasteData(callback: AsyncCallback<boolean>:void;

+

检查粘贴板中是否有内容

+

hasPasteData(): Promise<boolean>;

+

检查粘贴板中是否有内容

+

setPasteData(data: PasteData, callback: AsyncCallback<void>:void;

+

将 PasteData 写入粘贴板

+

setPasteData(data: PasteData): Promise<void>;

+

将 PasteData 写入粘贴板

+
+ + +**表 3** PasteData开放的主要方法 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

接口名

+

描述

+

addRecord(mimeType: string, value: ValueType): void;

+

将mimeType和对应值添加到 PasteData 对象中

+

getRecord(index: number): PasteDataRecord;

+

使用PasteData对象中的次序获取PasteDataRecord记录

+

hasType(mimeType: string): boolean;

+

判断DataProperty中是否有指定MIME类型的值

+

removeRecord(index: number): void;

+

基于PasteData中值的次序删除一条记录

+

replaceRecord(index: number, record: PasteDataRecord): void;

+

用PasteDataRecord记录替换PasteData中指定次序的记录

+

addHtmlRecord(htmlText: string): void;

+

将 HTML 文本记录添加到 PasteData 对象,并将 MIME 类型更新为 DataProperty 中的 PasteData#MIMETYPE_TEXT_HTML。

+

addWantRecord(want: Want): void;

+

将want记录添加到 PasteData 对象,并将 MIME 类型更新为 DataProperty 中的 PasteData#MIMETYPE_TEXT_WANT

+

addRecord(record: PasteDataRecord): void;

+

将 PasteRecord 添加到粘贴数据对象并更新数据属性中的 MIME 类型

+

addTextRecord(text: string): void;

+

将纯文本记录添加到 PasteData 对象,并将 MIME 类型更新为 DataProperty 中的 PasteData#MIMETYPE_TEXT_PLAIN

+

addUriRecord(uri: string): void;

+

将 URI 记录添加到 PasteData 对象,并将 MIME 类型更新为 DataProperty 中的 PasteData#MIMETYPE_TEXT_URI

getMimeTypes(): Array<string>;

+

粘贴板上所有内容的 MIME 类型

+

getPrimaryHtml(): string;

+

PasteData 对象中主要记录的 HTML 文本

+

getPrimaryWant(): Want;

+

PasteData 对象中的主记录的want

+

getPrimaryMimeType(): string;

+

PasteData 对象中主记录的 MIME 类型。

+

getPrimaryUri(): string;

+

PasteData 对象中主记录的 URI

getPrimaryPixelMap(): image.PixelMap;

+

PasteData 对象中主记录的 PixelMap。

+

getProperty(): PasteDataProperty;

+

获取剪贴板数据对象的属性

setProperty(property: PasteDataProperty): void;

+

设置属性描述对象,当前仅支持设置shareOption属性。

+

getRecordAt(index: number): PasteDataRecord;

+

基于指定索引的记录

+

getRecordCount(): number;

+

PasteData 对象中的记录数

+

hasMimeType(mimeType: string): boolean;

+

检查 DataProperty 中是否存在指定的 MIME 类型的数据

+

removeRecordAt(index: number): boolean;

+

根据指定索引删除记录

+

replaceRecordAt(index: number, record: PasteDataRecord): boolean;

+

用新记录替换指定记录

+
+ + +**表 4** PasteDataRecord开放的主要方法 + + + + + + + + + + + + + + + + + + + +

接口名

+

描述

+

convertToTextV9(callback: AsyncCallback<string>): void;

+

将 PasteData中的数据 转换为文本格式

+

convertToTextV9(): Promise<string>;

+

将 PasteData中的数据 转换为文本格式

+

convertToText(callback: AsyncCallback<string>): void;

+

将 PasteData 转换为文本内容的内容

+

convertToText(): Promise<void>;

+

将 PasteData 转换为文本内容的内容

+
+ +**表 5** PasteDataProperty参数说明 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

名称

+

类型

+

说明

+

additions{[key:string]}

+

object

+

附加属性数据键值对

+

mimeTypes

+

Array

+

PasteData 中所有记录的非重复 MIME 类型

+

tag

+

string

+

PasteData 对象的用户定义标签

+

timestamp

+

number

+

时间戳,指示何时将数据写入系统粘贴板。

+

localOnly

+

boolean

+

检查 PasteData 是否设置为仅用于本地访问。

shareOption

+

[ShareOption](https://gitee.com/openharmony/docs/blob/a4ead7d2fe7ac381133ba47c70c9df8cdfa95325/zh-cn/application-dev/reference/apis/js-apis-pasteboard.md#shareoption9)

+

指示剪贴板数据可以粘贴到的范围 。

+
+ + +**表 6** pasteboard主要属性说明 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

名称

+

类型

+

说明

+

MAX_RECORD_NUM

+

number

+

单个PasteData中所能包含的Record的数量上限。

+

MIMETYPE_TEXT_HTML

+

string

+

HTML text文本的MIME类型定义。

+

MIMETYPE_TEXT_WANT

+

string

+

Want的MIME类型定义。

+

MIMETYPE_TEXT_PLAIN

+

string

+

Plain text文本的MIME类型定义。

+

MIMETYPE_TEXT_URI

+

string

+

URI文本的MIME类型定义。

MIMETYPE_PIXELMAP

+

string

+

PixelMap的MIME类型定义 。

+

ValueType

+

string | image.PixelMap | Want | ArrayBuffer

+

value值的类型定义。

+
+ + +**表 7** PasteDataRecord主要属性说明 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

名称

+

类型

+

说明

+

htmlText

+

string

+

HTML文本内容。

+

want

+

[Want](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis/js-apis-application-want.md)

+

Want文本内容。

+

mimeType

+

string

+

数据类型。

+

plainText

+

string

+

文本内容。

+

uri

+

string

+

URI内容。

pixelMap

+

[image.PixelMap](https://gitee.com/openharmony/docs/blob/a4ead7d2fe7ac381133ba47c70c9df8cdfa95325/zh-cn/application-dev/reference/apis/js-apis-image.md#pixelmap7)

+

PixelMap内容。

+
+ + + +**表 8** ShareOption枚举类型说明 + + + + + + + + + + + + +

名称

+

说明

+

InApp

+

InApp表示仅允许同应用内粘贴。

+

LocalDevice

+

LocalDevice表示仅允许在此设备中粘贴。

+
+ +### 使用说明 + +剪贴板模块使用示例: + +``` +// 导入模块 +import pasteboard from '@ohos.pasteboard' + +//文本拷贝 +console.log('Get SystemPasteboard') +var systemPasteboard = pasteboard.getSystemPasteboard() +systemPasteboard.clear() + +var textData = 'Hello World!' +console.log('createPlainTextData = ' + textData) +var pasteData = pasteboard.createPlainTextData(textData) + +console.log('Writes PasteData to the pasteboard') +systemPasteboard.setPasteData(pasteData) + +console.log('Checks there is content in the pasteboard') +assert.equal(systemPasteboard.hasPasteData(), true) + +console.log('Checks the number of records') +pasteData = systemPasteboard.getPasteData() +assert.equal(pasteData.getRecordCount(), 1) + +console.log('Checks the pasteboard content') +assert.equal(pasteData.getPrimaryText(), textData) + +console.log('Checks there is a MIMETYPE_TEXT_PLAIN MIME type of data') +assert.equal(pasteData.hasMimeType(MIMETYPE_TEXT_PLAIN), true) +assert.equal(pasteData.getPrimaryMimeType(), MIMETYPE_TEXT_PLAIN) + +//剪贴板变化监听 +console.log('Off the content changes') +var systemPasteboard = pasteboard.getSystemPasteboard() +systemPasteboard.off(contentChanges) +systemPasteboard.clear() + +var textData = 'Hello World!' +console.log('createUriData = ' + textData) +var pasteData = pasteboard.createUriData(textData) + +console.log('Writes PasteData to the pasteboard') +systemPasteboard.setPasteData(pasteData) + +console.log('Checks there is content in the pasteboard') +assert.equal(systemPasteboard.hasPasteData(), true) + +console.log('Checks the number of records') +pasteData = systemPasteboard.getPasteData() +assert.equal(pasteData.getRecordCount(), 1) + +console.log('On the content changes') +systemPasteboard.on(contentChanges) + +console.log('Removes the Record') +assert.equal(pasteData.removeRecordAt(0), true) + +console.log('Writes PasteData to the pasteboard') +systemPasteboard.setPasteData(pasteData) + +console.log('Checks the number of records') +pasteData = systemPasteboard.getPasteData() +assert.equal(pasteData.getRecordCount(), 0) + +console.log('Checks there is no content in the pasteboard') +assert.equal(systemPasteboard.hasPasteData(), false) + +var textDataNew = 'Hello World!-New' +console.log('createUriData = ' + textDataNew) +var pasteData = pasteboard.createUriData(textDataNew) + +console.log('Writes PasteData to the pasteboard') +systemPasteboard.setPasteData(pasteData) + +console.log('Checks there is content in the pasteboard') +assert.equal(systemPasteboard.hasPasteData(), true) + +console.log('Checks the number of records') +pasteData = systemPasteboard.getPasteData() +assert.equal(pasteData.getRecordCount(), 1) + +console.log('Checks the pasteboard content') +assert.equal(pasteData.getRecordAt(0).plainText, textDataNew) + +//构建一个自定义类型的剪贴板内容对象 +var dataXml = new ArrayBuffer(256); +var pasteData = pasteboard.createData('app/xml', dataXml); + +//创建一条自定义数据内容条目 +var dataXml = new ArrayBuffer(256); +var pasteDataRecord = pasteboard.createRecord('app/xml', dataXml); + +//将一个PasteData中的内容强制转换为文本内容,使用callback异步回调 +var record = pasteboard.createUriRecord("dataability:///com.example.myapplication1/user.txt"); +record.convertToTextV9((err, data) => { + if (err) { + console.error('Failed to convert to text. Cause: ' + JSON.stringify(err)); + return; + } + console.info('Succeeded in converting to text. Data: ' + JSON.stringify(data)); +}); + +//将一个PasteData中的内容强制转换为文本内容,使用Promise异步回调 +var record = pasteboard.createUriRecord("dataability:///com.example.myapplication1/user.txt"); +record.convertToTextV9().then((data) => { + console.info('Succeeded in converting to text. Data: ' + JSON.stringify(data)); +}).catch((err) => { + console.error('Failed to convert to text. Cause: ' + JSON.stringify(err)); +}); + +//向当前剪贴板内容中添加一条自定义数据内容条目 +var pasteData = pasteboard.createUriData("dataability:///com.example.myapplication1/user.txt"); +var dataXml = new ArrayBuffer(256); +pasteData.addRecord('app/xml', dataXml); + +//获取剪贴板内容中指定下标的条目 +var pasteData = pasteboard.createPlainTextData("hello"); +var record = pasteData.getRecord(0); + +//检查剪贴板内容中是否有指定的MIME数据类型 +var pasteData = pasteboard.createPlainTextData("hello"); +var hasType = pasteData.hasType(pasteboard.MIMETYPE_TEXT_PLAIN); + +//移除剪贴板内容中指定下标的条目 +var pasteData = pasteboard.createPlainTextData("hello"); +pasteData.removeRecord(0); + +//替换剪贴板内容中指定下标的条目 +var pasteData = pasteboard.createPlainTextData("hello"); +var record = pasteboard.createUriRecord("dataability:///com.example.myapplication1/user.txt"); +pasteData.replaceRecord(0, record); + +//清空系统剪贴板内容,使用callback异步回调 +systemPasteboard.clearData((err, data) => { + if (err) { + console.error('Failed to clear the pasteboard. Cause: ' + JSON.stringify(err)); + return; + } + console.info('Succeeded in clearing the pasteboard.'); +}); + +//清空系统剪贴板内容,使用Promise异步回调 +systemPasteboard.clearData().then((data) => { + console.info('Succeeded in clearing the pasteboard.'); +}).catch((err) => { + console.error('Failed to clear the pasteboard. Cause: ' + JSON.stringify(err)); +}); + +//读取系统剪贴板内容,使用callback异步回调 +var systemPasteboard = pasteboard.getSystemPasteboard(); +systemPasteboard.getData((err, pasteData) => { + if (err) { + console.error('Failed to get PasteData. Cause: ' + err.message); + return; + } + var text = pasteData.getPrimaryText(); +}); + +//读取系统剪贴板内容,使用Promise异步回调 +var systemPasteboard = pasteboard.getSystemPasteboard(); +systemPasteboard.getData().then((pasteData) => { + var text = pasteData.getPrimaryText(); +}).catch((err) => { + console.error('Failed to get PasteData. Cause: ' + err.message); +}) + +//判断系统剪贴板中是否有内容,使用callback异步回调 +systemPasteboard.hasData((err, data) => { + if (err) { + console.error('Failed to check the PasteData. Cause: ' + JSON.stringify(err)); + return; + } + console.info('Succeeded in checking the PasteData. Data: ' + JSON.stringify(data)); +}); + +//判断系统剪贴板中是否有内容,使用Promise异步回调 +systemPasteboard.hasData().then((data) => { + console.info('Succeeded in checking the PasteData. Data: ' + JSON.stringify(data)); +}).catch((err) => { + console.error('Failed to check the PasteData. Cause: ' + JSON.stringify(err)); +}); + +//将数据写入系统剪贴板,使用callback异步回调 +var pasteData = pasteboard.createPlainTextData("content"); +var systemPasteboard = pasteboard.getSystemPasteboard(); +systemPasteboard.setData(pasteData, (err, data) => { + if (err) { + console.error('Failed to set PasteData. Cause: ' + err.message); + return; + } + console.info('Succeeded in setting PasteData.'); +}); + +//将数据写入系统剪贴板,使用Promise异步回调 +var pasteData = pasteboard.createPlainTextData("content"); +var systemPasteboard = pasteboard.getSystemPasteboard(); +systemPasteboard.setData(pasteData).then((data) => { + console.info('Succeeded in setting PasteData.'); +}).catch((err) => { + console.error('Failed to set PasteData. Cause: ' + err.message); +}); + +``` + +## 相关仓 + +**分布式数据管理子系统** + +[distributeddatamgr\_pasteboard](https://gitee.com/openharmony/distributeddatamgr_pasteboard) + diff --git a/pasteboard/bundle.json b/pasteboard/bundle.json new file mode 100644 index 00000000..d7028e4b --- /dev/null +++ b/pasteboard/bundle.json @@ -0,0 +1,113 @@ +{ + "name": "@ohos/pasteboard", + "description": "Allowing paste/copy functions", + "version": "3.0", + "license": "Apache License 2.0", + "publishAs": "code-segment", + "segment": { + "destPath": "foundation/distributeddatamgr/pasteboard" + }, + "dirs": {}, + "scripts": {}, + "component": { + "name": "pasteboard", + "subsystem": "distributeddatamgr", + "syscap": [ + "SystemCapability.MiscServices.Pasteboard" + ], + "features": [ + ], + "adapted_system_type": [ + "standard" + ], + "rom":"300KB", + "ram":"1024KB", + "deps": { + "components": [ + "ability_base", + "ability_runtime", + "access_token", + "app_file_service", + "bundle_framework", + "c_utils", + "common_event_service", + "device_info_manager", + "device_manager", + "dfs_service", + "dlp_permission_service", + "eventhandler", + "file_api", + "hisysevent", + "hitrace", + "hilog", + "init", + "input", + "imf", + "ipc", + "image_framework", + "napi", + "os_account", + "safwk", + "samgr", + "time_service", + "window_manager" + ], + "third_party": [ + "libuv", + "cJSON" + ] + }, + "build": { + "group_type": { + "base_group": [ + ], + "fwk_group": [ + "//foundation/distributeddatamgr/pasteboard/framework/framework:pasteboard_framework", + "//foundation/distributeddatamgr/pasteboard/framework/innerkits:pasteboard_client", + "//foundation/distributeddatamgr/pasteboard/interfaces/kits:pasteboard_napi" + ], + "service_group": [ + "//foundation/distributeddatamgr/pasteboard/etc/init:pasteboardservice.cfg", + "//foundation/distributeddatamgr/pasteboard/profile:distributeddatamgr_pasteboard_sa_profiles", + "//foundation/distributeddatamgr/pasteboard/services:pasteboard_service", + "//foundation/distributeddatamgr/pasteboard/services/etc:pasteboard.para.dac" + ] + }, + "inner_kits": [ + { + "name": "//foundation/distributeddatamgr/pasteboard/framework/innerkits:pasteboard_client", + "header": { + "header_files": [ + "pasteboard_client.h", + "paste_data.h", + "paste_data_record.h" + ], + "header_base":"//foundation/distributeddatamgr/pasteboard/framework/innerkits/include" + } + }, + { + "name": "//foundation/distributeddatamgr/pasteboard/framework/framework:pasteboard_framework", + "header": { + "header_files": [ + "clip/clip_plugin.h", + "device/clip_para.h", + "device/dm_adapter.h", + "common/block_object.h" + ], + "header_base":"//foundation/distributeddatamgr/pasteboard/framework/framework/include" + } + } + ], + "test": [ + "//foundation/distributeddatamgr/pasteboard/framework/test:PasteboardFrameworkTest", + "//foundation/distributeddatamgr/pasteboard/services/test:PasteboardServiceTest", + "//foundation/distributeddatamgr/pasteboard/test/fuzztest:fuzztest", + "//foundation/distributeddatamgr/pasteboard/interfaces/kits/napi/test/unittest/pasteboardapi:unittest", + "//foundation/distributeddatamgr/pasteboard/interfaces/kits/napi/test/unittest/pasteboardperf:unittest" + ] + }, + "hisysevent_config": [ + "//foundation/distributeddatamgr/pasteboard/pasteboardEvent.yaml" + ] + } +} \ No newline at end of file diff --git a/pasteboard/etc/init/BUILD.gn b/pasteboard/etc/init/BUILD.gn new file mode 100644 index 00000000..a4f66407 --- /dev/null +++ b/pasteboard/etc/init/BUILD.gn @@ -0,0 +1,23 @@ +# Copyright (C) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") + +################################################################################ + +ohos_prebuilt_etc("pasteboardservice.cfg") { + source = "pasteboardservice.cfg" + relative_install_dir = "init" + part_name = "pasteboard" + subsystem_name = "distributeddatamgr" +} diff --git a/pasteboard/etc/init/pasteboardservice.cfg b/pasteboard/etc/init/pasteboardservice.cfg new file mode 100644 index 00000000..16312ae1 --- /dev/null +++ b/pasteboard/etc/init/pasteboardservice.cfg @@ -0,0 +1,30 @@ +{ + "jobs" : [{ + "name" : "services:pasteboard_service", + "cmds" : [ + "mkdir /data/service/el1/public/database 0711 ddms ddms", + "mkdir /data/service/el1/public/database/pasteboard_service 02770 pasteboard ddms" + ] + } + ], + "services" : [{ + "name" : "pasteboard_service", + "path" : ["/system/bin/sa_main", "/system/profile/pasteboard_service.json"], + "uid" : "pasteboard", + "gid" : ["pasteboard", "shell", "dfs_share", "user_data_rw"], + "caps" : [], + "ondemand" : true, + "jobs" : { + "on-start" : "services:pasteboard_service" + }, + "secon" : "u:r:pasteboard_service:s0", + "sandbox" : 0, + "permission" : [ + "ohos.permission.DISTRIBUTED_DATASYNC", + "ohos.permission.ACCESS_SERVICE_DM", + "ohos.permission.PROXY_AUTHORIZATION_URI", + "ohos.permission.GET_BUNDLE_INFO" + ] + } + ] +} diff --git a/pasteboard/etc/init/pasteboardservice.rc b/pasteboard/etc/init/pasteboardservice.rc new file mode 100644 index 00000000..a42e1f47 --- /dev/null +++ b/pasteboard/etc/init/pasteboardservice.rc @@ -0,0 +1,20 @@ +# Copyright (C) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +on boot + start pasteboard_service +service pasteboard_service /system/bin/sa_main /system/profile/pasteboard_service.xml + class z_core + user system + group system shell + seclabel u:r:pasteboard_service:s0 diff --git a/pasteboard/figures/subsystem_architecture.png b/pasteboard/figures/subsystem_architecture.png new file mode 100644 index 0000000000000000000000000000000000000000..4e42bb1f61080ab3566fb4729e4b0b18e5d921f4 GIT binary patch literal 32044 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 literal 0 HcmV?d00001 diff --git a/pasteboard/figures/subsystem_architecture_zh.png b/pasteboard/figures/subsystem_architecture_zh.png new file mode 100644 index 0000000000000000000000000000000000000000..8efe18faf79b8256289a35bf245f7018afcb190e GIT binary patch literal 25627 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 H@9lp9-;^B1 literal 0 HcmV?d00001 diff --git a/pasteboard/framework/framework/BUILD.gn b/pasteboard/framework/framework/BUILD.gn new file mode 100644 index 00000000..950a07f5 --- /dev/null +++ b/pasteboard/framework/framework/BUILD.gn @@ -0,0 +1,84 @@ +# Copyright (c) 2022-2023 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import("//build/ohos.gni") +import("//build/ohos_var.gni") +import("//foundation/distributeddatamgr/pasteboard/pasteboard.gni") + +group("build_module") { + deps = [ ":pasteboard_framework" ] +} +config("module_public_config") { + visibility = [ ":*" ] + include_dirs = [ + "${pasteboard_utils_path}/native/include", + "include", + "include/device", + ] +} + +ohos_shared_library("pasteboard_framework") { + branch_protector_ret = "pac_ret" + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + } + sources = [ + "clip/clip_plugin.cpp", + "clip/default_clip.cpp", + "device/clip_para.cpp", + "device/dev_manager.cpp", + "device/dev_profile.cpp", + "device/distributed_module_config.cpp", + "device/dm_adapter.cpp", + "device/para_handle.cpp", + "serializable/serializable.cpp", + ] + cflags = [ "-Wno-multichar" ] + + cflags_cc = [ + "-fvisibility=hidden", + "-fstack-protector", + "-D_FORTIFY_SOURCE=2", + "-O2", + ] + + configs = [ ":module_public_config" ] + + configs += [ "//third_party/cJSON:cJSON_config" ] + + deps = [ "//third_party/cJSON:cjson" ] + + defines = [] + + public_configs = [ ":module_public_config" ] + + external_deps = [ + "c_utils:utils", + "hilog:libhilog", + "init:libbeget_proxy", + "init:libbegetutil", + ] + + if (pb_device_info_manager_part_enabled) { + external_deps += [ "device_info_manager:distributed_device_profile_client" ] + defines += [ "PB_DEVICE_INFO_MANAGER_ENABLE" ] + } + + if (pb_device_manager_part_enabled) { + external_deps += [ "device_manager:devicemanagersdk" ] + defines += [ "PB_DEVICE_MANAGER_ENABLE" ] + } + subsystem_name = "distributeddatamgr" + part_name = "pasteboard" +} diff --git a/pasteboard/framework/framework/clip/clip_plugin.cpp b/pasteboard/framework/framework/clip/clip_plugin.cpp new file mode 100644 index 00000000..6cf0b7ca --- /dev/null +++ b/pasteboard/framework/framework/clip/clip_plugin.cpp @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "clip/clip_plugin.h" + +#include "default_clip.h" +namespace OHOS::MiscServices { +std::map ClipPlugin::factories_; +DefaultClip g_defaultClip; +bool ClipPlugin::RegCreator(const std::string &name, Factory *factory) +{ + auto it = factories_.find(name); + if (it != factories_.end()) { + return false; + } + factories_[name] = factory; + return true; +} + +ClipPlugin *ClipPlugin::CreatePlugin(const std::string &name) +{ + auto it = factories_.find(name); + if (it == factories_.end() || it->second == nullptr) { + return &g_defaultClip; + } + return it->second->Create(); +} + +bool ClipPlugin::DestroyPlugin(const std::string &name, ClipPlugin *plugin) +{ + if (plugin == &g_defaultClip) { + return true; + } + + auto it = factories_.find(name); + if (it == factories_.end() || it->second == nullptr) { + return false; + } + return it->second->Destroy(plugin); +} + +ClipPlugin::~ClipPlugin() +{ +} + +std::vector ClipPlugin::GetTopEvents(uint32_t topN) +{ + (void)topN; + return std::vector(); +} + +std::vector ClipPlugin::GetTopEvents(uint32_t topN, int32_t user) +{ + (void)user; + (void)topN; + return std::vector(); +} + +void ClipPlugin::Clear() +{ +} + +void ClipPlugin::Clear(int32_t user) +{ + (void)user; +} +} // namespace OHOS::MiscServices diff --git a/pasteboard/framework/framework/clip/default_clip.cpp b/pasteboard/framework/framework/clip/default_clip.cpp new file mode 100644 index 00000000..cf720107 --- /dev/null +++ b/pasteboard/framework/framework/clip/default_clip.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "default_clip.h" +namespace OHOS::MiscServices { +int32_t DefaultClip::SetPasteData(const GlobalEvent &event, const std::vector &data) +{ + return 0; +} + +int32_t DefaultClip::GetPasteData(const GlobalEvent &event, std::vector &data) +{ + return 0; +} + +std::vector DefaultClip::GetTopEvents(uint32_t topN, int32_t user) +{ + return std::vector(); +} + +void DefaultClip::Clear(int32_t user) +{ +} +} // namespace OHOS::MiscServices \ No newline at end of file diff --git a/pasteboard/framework/framework/clip/default_clip.h b/pasteboard/framework/framework/clip/default_clip.h new file mode 100644 index 00000000..d7e0ea96 --- /dev/null +++ b/pasteboard/framework/framework/clip/default_clip.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_DISTRIBUTED_DATA_PASTEBOARD_SERVICES_FRAMEWORK_CLIPS_DEFAULT_CLIPS_H +#define OHOS_DISTRIBUTED_DATA_PASTEBOARD_SERVICES_FRAMEWORK_CLIPS_DEFAULT_CLIPS_H +#include "clip/clip_plugin.h" +namespace OHOS::MiscServices { +class DefaultClip : public ClipPlugin { +public: + int32_t SetPasteData(const GlobalEvent &event, const std::vector &data) override; + int32_t GetPasteData(const GlobalEvent &event, std::vector &data) override; + std::vector GetTopEvents(uint32_t topN, int32_t user) override; + void Clear(int32_t user) override; +}; +} // namespace OHOS::MiscServices +#endif // OHOS_DISTRIBUTED_DATA_PASTEBOARD_SERVICES_FRAMEWORK_CLIPS_DEFAULT_CLIPS_H diff --git a/pasteboard/framework/framework/device/clip_para.cpp b/pasteboard/framework/framework/device/clip_para.cpp new file mode 100644 index 00000000..72243961 --- /dev/null +++ b/pasteboard/framework/framework/device/clip_para.cpp @@ -0,0 +1,223 @@ +/* + * Copyright (C) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "clip_para.h" + +#include +#include "pasteboard_hilog.h" + +namespace OHOS { +namespace MiscServices { +using namespace std::chrono; + +ClipPara::ClipPara() +{ +} + +ClipPara &ClipPara::GetInstance() +{ + static ClipPara instance; + return instance; +} + +void ClipPara::InitMemberVariable() +{ + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "InitMemberVariable"); + sendInformation_ = nullptr; + remoteExpiration_ = 0; + lastSyncNetworkId_ = ""; + isPullEvent_ = false; + isPullEventResult_ = false; + isPasted_ = false; + activeSync_ = false; + frameNum_ = 0; +} + +bool ClipPara::HasRemoteData() +{ + uint64_t curTime = + static_cast(duration_cast(system_clock::now().time_since_epoch()).count()); + return sendInformation_ != nullptr && remoteExpiration_ > curTime; +} + +std::string ClipPara::GetLastLocalSyncKey() +{ + std::lock_guard lockGuard(mutex_); + return lastLocalSyncKey_; +} + +std::string ClipPara::GetLastRemoteSyncKey() +{ + return lastRemoteSyncKey_; +} + +std::string ClipPara::GetLastSyncNetworkId() +{ + return lastSyncNetworkId_; +} + +uint64_t ClipPara::GetLocalExpiration() +{ + return localExpiration_.load(); +} + +uint64_t ClipPara::GetRemoteExpiration() +{ + return remoteExpiration_; +} + +std::shared_ptr ClipPara::GetSendInformation() +{ + return sendInformation_; +} + +uint32_t ClipPara::GetFirstStageValue() +{ + return firstStageValue_.load(); +} + +uint32_t ClipPara::GetSecondStageValue() +{ + return secondStageValue_.load(); +} + +bool ClipPara::GetPullEvent() +{ + return isPullEvent_.load(); +} + +bool ClipPara::GetPullEventResult() +{ + return isPullEventResult_.load(); +} + +bool ClipPara::GetPasted() +{ + return isPasted_.load(); +} + +bool ClipPara::GetActiveSync() +{ + return activeSync_.load(); +} + +uint8_t ClipPara::GetFrameNum() +{ + return frameNum_.load(); +} + +void ClipPara::SetLastLocalSyncKey(const std::string lastSyncKey) +{ + std::lock_guard lockGuard(mutex_); + lastLocalSyncKey_ = lastSyncKey; +} + +void ClipPara::SetLastRemoteSyncKey(const std::string lastRemoteSyncKey) +{ + lastRemoteSyncKey_ = lastRemoteSyncKey; +} + +void ClipPara::SetLastSyncNetworkId(const std::string lastSyncNetworkId) +{ + lastSyncNetworkId_ = lastSyncNetworkId; +} + +void ClipPara::SetLocalExpiration(const uint64_t expiration) +{ + localExpiration_.store(expiration); +} + +void ClipPara::SetRemoteExpiration(const uint64_t remoteExpiration) +{ + remoteExpiration_.store(remoteExpiration); +} + +void ClipPara::SetSendInformation(const ClipPara::SendInformation &senderInformation) +{ + sendInformation_ = std::make_shared(senderInformation); +} + +void ClipPara::SetFirstStageValue(const uint32_t firstStageValue) +{ + firstStageValue_.store(firstStageValue); +} + +void ClipPara::SetSecondStageValue(const uint32_t secondStageValue) +{ + secondStageValue_.store(secondStageValue); +} + +void ClipPara::SetPullEvent(const bool isPullEvent) +{ + isPullEvent_.store(isPullEvent); +} + +void ClipPara::SetPullEventResult(const bool isPullEventResult) +{ + isPullEventResult_.store(isPullEventResult); +} + +void ClipPara::SetPasted(const bool isPasted) +{ + isPasted_.store(isPasted); +} + +void ClipPara::SetActiveSync(const bool activeSync) +{ + activeSync_.store(activeSync); +} + +void ClipPara::SetFrameNum(const uint8_t frameNum) +{ + frameNum_.store(frameNum); +} + +void ClipPara::UpdateStageValue(const uint64_t &expiration, bool isPasting) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "start, firstStageValue = %{public}s, secondStageValue = %{public}s", + std::to_string(firstStageValue_).c_str(), std::to_string(secondStageValue_).c_str()); + if (!isPullEvent_ && !isPasting) { + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "not do pre-establish"); + return; + } + + if (isPasted_) { + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "stage value has been update"); + return; + } + uint64_t curTime = + static_cast(duration_cast(system_clock::now().time_since_epoch()).count()); + if (isPasting && expiration > curTime) { + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "UpdateStageValue"); + isPasted_ = true; + if ((firstStageValue_ == MIN_STAGE_VALUE && secondStageValue_ == MAX_STAGE_VALUE) || + firstStageValue_ != MIN_STAGE_VALUE) { + firstStageValue_ = MAX_STAGE_VALUE; + secondStageValue_ = MIN_STAGE_VALUE; + } else { + secondStageValue_.fetch_add(1); + } + } else { + if (firstStageValue_ == MIN_STAGE_VALUE) { + auto diffValue = (secondStageValue_ != MIN_STAGE_VALUE) ? 1 : 0; + secondStageValue_.fetch_sub(diffValue); + } else { + firstStageValue_.fetch_sub(1); + } + } + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "end, firstStageValue = %{public}s, secondStageValue = %{public}s", + std::to_string(firstStageValue_).c_str(), std::to_string(secondStageValue_).c_str()); +} +} // namespace MiscServices +} // namespace OHOS \ No newline at end of file diff --git a/pasteboard/framework/framework/device/dev_manager.cpp b/pasteboard/framework/framework/device/dev_manager.cpp new file mode 100644 index 00000000..11f05694 --- /dev/null +++ b/pasteboard/framework/framework/device/dev_manager.cpp @@ -0,0 +1,200 @@ +/* + * Copyright (C) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "dev_manager.h" + +#include + +#include "dev_profile.h" +#include "distributed_module_config.h" +#include "pasteboard_hilog.h" +#ifdef PB_DEVICE_MANAGER_ENABLE +#include "device_manager.h" +#include "device_manager_callback.h" +#endif +namespace OHOS { +namespace MiscServices { +constexpr const char *PKG_NAME = "pasteboard_service"; +constexpr int32_t DM_OK = 0; +constexpr const int32_t DELAY_TIME = 200; +constexpr const uint32_t FIRST_VERSION = 4; +#ifdef PB_DEVICE_MANAGER_ENABLE +using namespace OHOS::DistributedHardware; + +class PasteboardDevStateCallback : public DistributedHardware::DeviceStateCallback { +public: + void OnDeviceOnline(const DistributedHardware::DmDeviceInfo &deviceInfo) override; + void OnDeviceOffline(const DmDeviceInfo &deviceInfo) override; + void OnDeviceChanged(const DmDeviceInfo &deviceInfo) override; + void OnDeviceReady(const DmDeviceInfo &deviceInfo) override; +}; + +class PasteboardDmInitCallback : public DistributedHardware::DmInitCallback { +public: + void OnRemoteDied() override; +}; + +void PasteboardDevStateCallback::OnDeviceOnline(const DmDeviceInfo &deviceInfo) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "start."); + DevManager::GetInstance().Online(deviceInfo.networkId); +} + +void PasteboardDevStateCallback::OnDeviceOffline(const DmDeviceInfo &deviceInfo) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "start."); + DevManager::GetInstance().Offline(deviceInfo.networkId); +} + +void PasteboardDevStateCallback::OnDeviceChanged(const DmDeviceInfo &deviceInfo) +{ +} + +void PasteboardDevStateCallback::OnDeviceReady(const DmDeviceInfo &deviceInfo) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "start."); + (void)deviceInfo; + DevManager::GetInstance().OnReady(); +} + +void PasteboardDmInitCallback::OnRemoteDied() +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "dm device manager died, init it again"); + DevManager::GetInstance().Init(); +} +#endif + +DevManager::DevManager() +{ +} + +void DevManager::UnregisterDevCallback() +{ + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "start"); + auto &deviceManager = DeviceManager::GetInstance(); + deviceManager.UnRegisterDevStateCallback(PKG_NAME); + deviceManager.UnInitDeviceManager(PKG_NAME); + DevProfile::GetInstance().UnsubscribeAllProfileEvents(); +} + +int32_t DevManager::Init() +{ +#ifdef PB_DEVICE_MANAGER_ENABLE + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "start"); + RetryInBlocking([]() -> bool { + auto initCallback = std::make_shared(); + int32_t errNo = DeviceManager::GetInstance().InitDeviceManager(PKG_NAME, initCallback); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "InitDeviceManager ret %{public}d", errNo); + return errNo == DM_OK; + }); + RetryInBlocking([]() -> bool { + auto stateCallback = std::make_shared(); + auto errNo = DeviceManager::GetInstance().RegisterDevStateCallback(PKG_NAME, "", stateCallback); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "RegisterDevStateCallback ret %{public}d", errNo); + return errNo == DM_OK; + }); + DistributedModuleConfig::GetDeviceNum(); +#endif + return DM_OK; +} + +DevManager &DevManager::GetInstance() +{ + static DevManager instance; + return instance; +} + +void DevManager::Online(const std::string &networkId) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "start."); + DevProfile::GetInstance().SubscribeProfileEvent(networkId); + DistributedModuleConfig::ForceNotify(); + DistributedModuleConfig::Notify(); +} + +void DevManager::Offline(const std::string &networkId) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "start."); + DevProfile::GetInstance().UnSubscribeProfileEvent(networkId); + DistributedModuleConfig::Notify(); +} + +void DevManager::OnReady() +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "start."); + DevProfile::GetInstance().OnReady(); +} + +void DevManager::RetryInBlocking(DevManager::Function func) const +{ + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "retry start"); + constexpr int32_t RETRY_TIMES = 300; + for (int32_t i = 0; i < RETRY_TIMES; ++i) { + if (func()) { + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "retry result: %{public}d times", i); + return; + } + std::this_thread::sleep_for(std::chrono::milliseconds(DELAY_TIME)); + } + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "retry failed"); +} + +std::vector DevManager::GetNetworkIds() +{ +#ifdef PB_DEVICE_MANAGER_ENABLE + std::vector devices; + int32_t ret = DeviceManager::GetInstance().GetTrustedDeviceList(PKG_NAME, "", devices); + if (ret != 0) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "GetTrustedDeviceList failed!"); + return {}; + } + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "devicesNums = %{public}zu.", devices.size()); + if (devices.empty()) { + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "no device online!"); + return {}; + } + std::vector networkIds; + for (auto &item : devices) { + networkIds.emplace_back(item.networkId); + } + return networkIds; +#else + return {}; +#endif +} + +std::vector DevManager::GetOldNetworkIds() +{ +#ifdef PB_DEVICE_MANAGER_ENABLE + std::vector networkIds = GetNetworkIds(); + if (networkIds.empty()) { + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "no device online!"); + return {}; + } + std::vector oldNetworkIds; + for (auto &item : networkIds) { + uint32_t versionId = 3; + DevProfile::GetInstance().GetRemoteDeviceVersion(item, versionId); + if (versionId >= FIRST_VERSION) { + continue; + } + oldNetworkIds.emplace_back(item); + } + return oldNetworkIds; +#else + return {}; +#endif +} +} // namespace MiscServices +} // namespace OHOS diff --git a/pasteboard/framework/framework/device/dev_profile.cpp b/pasteboard/framework/framework/device/dev_profile.cpp new file mode 100644 index 00000000..03a1b118 --- /dev/null +++ b/pasteboard/framework/framework/device/dev_profile.cpp @@ -0,0 +1,278 @@ +/* + * Copyright (C) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "dev_profile.h" + +#include +#include + +#include "cJSON.h" +#include "dev_manager.h" +#include "distributed_module_config.h" +#include "dm_adapter.h" +#include "para_handle.h" +#include "pasteboard_hilog.h" +#include "service_characteristic_profile.h" +#include "subscribe_info.h" + +#ifdef PB_DEVICE_INFO_MANAGER_ENABLE +#include "distributed_device_profile_client.h" +#endif // PB_DEVICE_INFO_MANAGER_ENABLE + +namespace OHOS { +namespace MiscServices { +#ifdef PB_DEVICE_INFO_MANAGER_ENABLE +using namespace OHOS::DeviceProfile; +constexpr const int32_t HANDLE_OK = 0; +constexpr const uint32_t NOT_SUPPORT = 0; +constexpr const uint32_t SUPPORT = 1; + +constexpr const char *SERVICE_ID = "pasteboardService"; +constexpr const char *CHARACTER_ID = "supportDistributedPasteboard"; +constexpr const char *VERSION_ID = "PasteboardVersionId"; + +void DevProfile::PasteboardProfileEventCallback::OnSyncCompleted(const SyncResult &syncResults) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "OnSyncCompleted."); +} + +void DevProfile::PasteboardProfileEventCallback::OnProfileChanged(const ProfileChangeNotification &changeNotification) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "OnProfileChanged start."); +} +#endif + +DevProfile::DevProfile() +{ +} + +DevProfile &DevProfile::GetInstance() +{ + static DevProfile instance; + return instance; +} + +void DevProfile::Init() +{ + ParaHandle::GetInstance().WatchEnabledStatus(ParameterChange); +} + +void DevProfile::OnReady() +{ +} + +void DevProfile::ParameterChange(const char *key, const char *value, void *context) +{ + auto enabledKey = ParaHandle::DISTRIBUTED_PASTEBOARD_ENABLED_KEY; + if (strncmp(key, enabledKey, strlen(enabledKey)) != 0) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "key is error."); + return; + } + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "ParameterChange, key = %{public}s, value = %{public}s.", key, value); + DevProfile::GetInstance().PutEnabledStatus(value); +} + +void DevProfile::PutEnabledStatus(const std::string &enabledStatus) +{ +#ifdef PB_DEVICE_INFO_MANAGER_ENABLE + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "PutEnabledStatus, start"); + ServiceCharacteristicProfile profile; + profile.SetServiceId(SERVICE_ID); + profile.SetServiceType(SERVICE_ID); + cJSON *jsonObject = cJSON_CreateObject(); + cJSON_AddNumberToObject(jsonObject, CHARACTER_ID, NOT_SUPPORT); + localEnable_ = false; + if (enabledStatus == "true") { + cJSON_ReplaceItemInObject(jsonObject, CHARACTER_ID, cJSON_CreateNumber(SUPPORT)); + localEnable_ = true; + } + cJSON_AddNumberToObject(jsonObject, VERSION_ID, FIRST_VERSION); + char *jsonString = cJSON_PrintUnformatted((jsonObject)); + profile.SetCharacteristicProfileJson(jsonString); + cJSON_Delete(jsonObject); + free(jsonString); + int32_t errNo = DistributedDeviceProfileClient::GetInstance().PutDeviceProfile(profile); + if (errNo != HANDLE_OK) { + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "PutDeviceProfile failed, %{public}d", errNo); + return; + } +#else + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "PB_DEVICE_INFO_MANAGER_ENABLE not defined"); + return; +#endif +} + +void DevProfile::GetEnabledStatus(const std::string &networkId, std::string &enabledStatus) +{ +#ifdef PB_DEVICE_INFO_MANAGER_ENABLE + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "GetEnabledStatus start."); + std::string udid = DMAdapter::GetInstance().GetUdidByNetworkId(networkId); + if (udid.empty()) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "GetUdidByNetworkId failed"); + return; + } + ServiceCharacteristicProfile profile; + int32_t ret = DistributedDeviceProfileClient::GetInstance().GetDeviceProfile(udid, SERVICE_ID, profile); + if (ret != HANDLE_OK) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "GetDeviceProfile failed, %{public}.5s.", udid.c_str()); + return; + } + const auto &jsonData = profile.GetCharacteristicProfileJson(); + cJSON *jsonObject = cJSON_Parse(jsonData.c_str()); + if (jsonObject == nullptr) { + cJSON_Delete(jsonObject); + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "json parse failed."); + return; + } + + enabledStatus = "false"; + if (cJSON_GetNumberValue(cJSON_GetObjectItem(jsonObject, CHARACTER_ID)) == SUPPORT) { + enabledStatus = "true"; + } + cJSON_Delete(jsonObject); + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "GetEnabledStatus success %{public}s.", enabledStatus.c_str()); +#else + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "PB_DEVICE_INFO_MANAGER_ENABLE not defined"); + return; +#endif +} + +void DevProfile::GetRemoteDeviceVersion(const std::string &networkId, uint32_t &versionId) +{ +#ifdef PB_DEVICE_INFO_MANAGER_ENABLE + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "GetRemoteDeviceVersion start."); + std::string udid = DMAdapter::GetInstance().GetUdidByNetworkId(networkId); + if (udid.empty()) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "GetUdidByNetworkId failed."); + return; + } + ServiceCharacteristicProfile profile; + int32_t ret = DistributedDeviceProfileClient::GetInstance().GetDeviceProfile(udid, SERVICE_ID, profile); + if (ret != HANDLE_OK) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "GetDeviceProfile failed, %{public}.5s.", udid.c_str()); + return; + } + const auto &jsonData = profile.GetCharacteristicProfileJson(); + cJSON *jsonObject = cJSON_Parse(jsonData.c_str()); + if (jsonObject == nullptr) { + cJSON_Delete(jsonObject); + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "json parse failed."); + return; + } + if (cJSON_GetNumberValue(cJSON_GetObjectItem(jsonObject, VERSION_ID)) == FIRST_VERSION) { + versionId = FIRST_VERSION; + } + cJSON_Delete(jsonObject); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "GetRemoteDeviceVersion success, versionId = %{public}d.", versionId); +#else + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "PB_DEVICE_INFO_MANAGER_ENABLE not defined"); + return; +#endif +} + +void DevProfile::SubscribeProfileEvent(const std::string &networkId) +{ +#ifdef PB_DEVICE_INFO_MANAGER_ENABLE + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "start, networkId = %{public}.5s", networkId.c_str()); + std::string udid = DMAdapter::GetInstance().GetUdidByNetworkId(networkId); + if (udid.empty()) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "GetUdidByNetworkId failed"); + return; + } + std::lock_guard mutexLock(callbackMutex_); + if (callback_.find(udid) != callback_.end()) { + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "networkId = %{public}.5s already exists.", udid.c_str()); + return; + } + auto profileCallback = std::make_shared(); + callback_[udid] = profileCallback; + std::list serviceIds = { SERVICE_ID }; + ExtraInfo extraInfo; + extraInfo["deviceId"] = udid; + extraInfo["serviceIds"] = serviceIds; + + std::list subscribeInfos; + SubscribeInfo changeEventInfo; + changeEventInfo.profileEvent = ProfileEvent::EVENT_PROFILE_CHANGED; + changeEventInfo.extraInfo = std::move(extraInfo); + subscribeInfos.emplace_back(changeEventInfo); + + SubscribeInfo syncEventInfo; + syncEventInfo.profileEvent = ProfileEvent::EVENT_SYNC_COMPLETED; + subscribeInfos.emplace_back(syncEventInfo); + + std::list failedEvents; + int32_t errCode = DistributedDeviceProfileClient::GetInstance().SubscribeProfileEvents(subscribeInfos, + profileCallback, failedEvents); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "SubscribeProfileEvent result, errCode = %{public}d.", errCode); +#else + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "PB_DEVICE_INFO_MANAGER_ENABLE not defined"); + return; +#endif +} + +void DevProfile::UnSubscribeProfileEvent(const std::string &networkId) +{ +#ifdef PB_DEVICE_INFO_MANAGER_ENABLE + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "start, networkId = %{public}.5s", networkId.c_str()); + std::string udid = DMAdapter::GetInstance().GetUdidByNetworkId(networkId); + if (udid.empty()) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "GetUdidByNetworkId failed, %{public}.5s.", udid.c_str()); + return; + } + std::lock_guard mutexLock(callbackMutex_); + auto it = callback_.find(udid); + if (it == callback_.end()) { + return; + } + std::list profileEvents; + profileEvents.emplace_back(ProfileEvent::EVENT_PROFILE_CHANGED); + std::list failedEvents; + int32_t errCode = DistributedDeviceProfileClient::GetInstance().UnsubscribeProfileEvents(profileEvents, + it->second, failedEvents); + callback_.erase(it); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "UnsubscribeProfileEvent result, errCode = %{public}d.", errCode); +#else + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "PB_DEVICE_INFO_MANAGER_ENABLE not defined"); + return; +#endif +} + +void DevProfile::UnsubscribeAllProfileEvents() +{ +#ifdef PB_DEVICE_INFO_MANAGER_ENABLE + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "UnsubscribeAllProfileEvents start."); + std::lock_guard mutexLock(callbackMutex_); + for (auto it = callback_.begin(); it != callback_.end(); ++it) { + std::list profileEvents; + profileEvents.emplace_back(ProfileEvent::EVENT_PROFILE_CHANGED); + std::list failedEvents; + int32_t ret = DistributedDeviceProfileClient::GetInstance().UnsubscribeProfileEvents(profileEvents, + it->second, failedEvents); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "errCode = %{public}d.", ret); + it = callback_.erase(it); + } +#else + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "PB_DEVICE_INFO_MANAGER_ENABLE not defined"); + return; +#endif +} + +bool DevProfile::GetLocalEnable() +{ + return localEnable_; +} + +} // namespace MiscServices +} // namespace OHOS diff --git a/pasteboard/framework/framework/device/distributed_module_config.cpp b/pasteboard/framework/framework/device/distributed_module_config.cpp new file mode 100644 index 00000000..74df930c --- /dev/null +++ b/pasteboard/framework/framework/device/distributed_module_config.cpp @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "distributed_module_config.h" + +#include "dev_manager.h" +#include "dev_profile.h" +#include "pasteboard_hilog.h" + +namespace OHOS { +namespace MiscServices { +bool DistributedModuleConfig::status_ = false; +size_t DistributedModuleConfig::deviceNums_ = 0; +DistributedModuleConfig::Observer DistributedModuleConfig::observer_ = nullptr; +bool DistributedModuleConfig::IsOn() +{ + if (deviceNums_ != 0) { + Notify(); + } + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "device online nums: %{public}zu, status_:%{public}d", + deviceNums_, status_); + return status_; +} + +void DistributedModuleConfig::Watch(Observer observer) +{ + observer_ = std::move(observer); +} + +void DistributedModuleConfig::ForceNotify() +{ + if (observer_ != nullptr) { + observer_(true); + } +} + +void DistributedModuleConfig::Notify() +{ + bool newStatus = GetEnabledStatus(); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "Notify, status:%{public}d, newStatus:%{public}d", + status_, newStatus); + if (newStatus != status_) { + status_ = newStatus; + if (observer_ != nullptr) { + observer_(newStatus); + } + } +} + +void DistributedModuleConfig::GetDeviceNum() +{ + auto networkIds = DevManager::GetInstance().GetNetworkIds(); + deviceNums_ = networkIds.size(); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "GetDeviceNum devicesNum = %{public}zu.", deviceNums_); +} + +bool DistributedModuleConfig::GetEnabledStatus() +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "GetEnabledStatus start."); + if (!DevProfile::GetInstance().GetLocalEnable()) { + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "GetLocalEnable false."); + return false; + } + + auto networkIds = DevManager::GetInstance().GetNetworkIds(); + deviceNums_ = networkIds.size(); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "device online nums: %{public}zu", deviceNums_); + std::string remoteEnabledStatus = "false"; + for (auto &id : networkIds) { + DevProfile::GetInstance().GetEnabledStatus(id, remoteEnabledStatus); + if (remoteEnabledStatus == "true") { + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "remoteEnabledStatus true."); + return true; + } + } + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "remoteEnabledStatus = %{public}s.", remoteEnabledStatus.c_str()); + return false; +} +} // namespace MiscServices +} // namespace OHOS \ No newline at end of file diff --git a/pasteboard/framework/framework/device/dm_adapter.cpp b/pasteboard/framework/framework/device/dm_adapter.cpp new file mode 100644 index 00000000..333a0560 --- /dev/null +++ b/pasteboard/framework/framework/device/dm_adapter.cpp @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "device/dm_adapter.h" + +#include "pasteboard_hilog.h" +#ifdef PB_DEVICE_MANAGER_ENABLE +#include "device_manager.h" +#include "device_manager_callback.h" +#endif +namespace OHOS::MiscServices { +constexpr size_t DMAdapter::MAX_ID_LEN; +#ifdef PB_DEVICE_MANAGER_ENABLE +class DmStateObserver : public DeviceStateCallback { +public: + DmStateObserver(const std::function online, + const std::function onReady) + :online_(std::move(online)), onReady_(std::move(onReady)) + { + } + + void OnDeviceOnline(const DmDeviceInfo &deviceInfo) override + { + if (online_ == nullptr) { + return; + } + online_(deviceInfo); + } + + void OnDeviceOffline(const DmDeviceInfo &deviceInfo) override + { + } + void OnDeviceChanged(const DmDeviceInfo &deviceInfo) override + { + } + void OnDeviceReady(const DmDeviceInfo &deviceInfo) override + { + if (onReady_ == nullptr) { + return; + } + onReady_(deviceInfo); + } + +private: + std::function online_; + std::function onReady_; +}; + +class DmDeath : public DmInitCallback, public std::enable_shared_from_this { +public: + DmDeath(std::shared_ptr observer, std::string pkgName) + : observer_(observer), pkgName_(std::move(pkgName)) + { + } + void OnRemoteDied() override + { + DeviceManager::GetInstance().InitDeviceManager(pkgName_, shared_from_this()); + DeviceManager::GetInstance().RegisterDevStateCallback(pkgName_, "", observer_); + } + +private: + std::shared_ptr observer_; + std::string pkgName_; +}; +#endif + +DMAdapter::DMAdapter() +{ +} + +DMAdapter::~DMAdapter() +{ +} + +DMAdapter &DMAdapter::GetInstance() +{ + static DMAdapter instance; + return instance; +} + +bool DMAdapter::Initialize(const std::string &pkgName) +{ +#ifdef PB_DEVICE_MANAGER_ENABLE + auto stateObserver = std::make_shared([this](const DmDeviceInfo &deviceInfo) { + observers_.ForEach([&deviceInfo](auto &key, auto &value) { + value->Online(deviceInfo.networkId); + return false; + }); + }, [this](const DmDeviceInfo &deviceInfo) { + observers_.ForEach([&deviceInfo](auto &key, auto &value) { + value->OnReady(deviceInfo.networkId); + return false; + }); + }); + pkgName_ = pkgName + NAME_EX; + auto deathObserver = std::make_shared(stateObserver, pkgName_); + deathObserver->OnRemoteDied(); +#endif + return false; +} + +const std::string &DMAdapter::GetLocalDeviceUdid() +{ +#ifdef PB_DEVICE_MANAGER_ENABLE + std::lock_guard lockGuard(mutex_); + if (!localDeviceUdid_.empty()) { + return localDeviceUdid_; + } + + DmDeviceInfo info; + int32_t ret = DeviceManager::GetInstance().GetLocalDeviceInfo(pkgName_, info); + if (ret != 0) { + return invalidDeviceUdid_; + } + DeviceManager::GetInstance().GetUdidByNetworkId(pkgName_, info.networkId, localDeviceUdid_); + if (!localDeviceUdid_.empty()) { + return localDeviceUdid_; + } +#endif + return invalidDeviceUdid_; +} + +std::string DMAdapter::GetDeviceName(const std::string &networkId) +{ +#ifdef PB_DEVICE_MANAGER_ENABLE + std::vector devices; + (void)DeviceManager::GetInstance().GetTrustedDeviceList(pkgName_, "", devices); + for (auto &device : devices) { + if (device.networkId == networkId) { + return device.deviceName; + } + } +#endif + return DEVICE_INVALID_NAME; +} + +const std::string DMAdapter::GetLocalNetworkId() +{ +#ifdef PB_DEVICE_MANAGER_ENABLE + DmDeviceInfo info; + int32_t ret = DeviceManager::GetInstance().GetLocalDeviceInfo(pkgName_, info); + auto networkId = std::string(info.networkId); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "ret: %{public}d, networkId:%{public}s", ret, networkId.c_str()); + if (ret == 0 && !networkId.empty()) { + return networkId; + } +#endif + return invalidNetworkId_; +} + +int32_t DMAdapter::GetRemoteDeviceInfo(const std::string &networkId, DmDeviceInfo &remoteDevice) +{ +#ifdef PB_DEVICE_MANAGER_ENABLE + std::vector devices; + (void)DeviceManager::GetInstance().GetTrustedDeviceList(pkgName_, "", devices); + for (auto &device : devices) { + if (device.networkId == networkId) { + remoteDevice = device; + return RESULT_OK; + } + } +#endif + return -1; +} + +std::string DMAdapter::GetUdidByNetworkId(const std::string &networkId) +{ +#ifdef PB_DEVICE_MANAGER_ENABLE + std::string udid; + int32_t ret = DeviceManager::GetInstance().GetUdidByNetworkId(pkgName_, networkId, udid); + if (ret == 0 && !udid.empty()) { + return udid; + } +#endif + return invalidUdid_; +} + +void DMAdapter::Register(DMObserver *observer) +{ + observers_.Insert(observer, observer); +} + +void DMAdapter::Unregister(DMObserver *observer) +{ + observers_.Erase(observer); +} +} // namespace OHOS::MiscServices \ No newline at end of file diff --git a/pasteboard/framework/framework/device/para_handle.cpp b/pasteboard/framework/framework/device/para_handle.cpp new file mode 100644 index 00000000..cf8498cc --- /dev/null +++ b/pasteboard/framework/framework/device/para_handle.cpp @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "para_handle.h" + +#include "pasteboard_hilog.h" +namespace OHOS { +namespace MiscServices { +constexpr int32_t HANDLE_OK = 0; +ParaHandle::ParaHandle() +{ +} + +ParaHandle &ParaHandle::GetInstance() +{ + static ParaHandle instance; + return instance; +} + +void ParaHandle::Init() +{ + auto status = GetEnabledStatus(); + if (!status.empty()) { + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "local device param already been set"); + return; + } + + auto errNo = SetParameter(DISTRIBUTED_PASTEBOARD_ENABLED_KEY, DISTRIBUTED_PASTEBOARD_ENABLED_DEFAULT_VALUE); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "SetParameter, errNo = %{public}d.", errNo); +} + +void ParaHandle::WatchEnabledStatus(ParameterChgPtr ptr) const +{ + auto errNo = WatchParameter(DISTRIBUTED_PASTEBOARD_ENABLED_KEY, ptr, nullptr); + if (errNo != HANDLE_OK) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "local device param watch failed, %{public}d", errNo); + } +} + +std::string ParaHandle::GetEnabledStatus() const +{ + char value[CONFIG_LEN] = { 0 }; + auto errNo = GetParameter(DISTRIBUTED_PASTEBOARD_ENABLED_KEY, "", value, CONFIG_LEN); + if (errNo > HANDLE_OK) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "GetParameter success, value = %{public}s.", value); + return value; + } + return ""; +} +} // namespace MiscServices +} // namespace OHOS diff --git a/pasteboard/framework/framework/include/api/visibility.h b/pasteboard/framework/framework/include/api/visibility.h new file mode 100644 index 00000000..cd29b184 --- /dev/null +++ b/pasteboard/framework/framework/include/api/visibility.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_DISTRIBUTED_API_VISIBILITY_H +#define OHOS_DISTRIBUTED_API_VISIBILITY_H + +#ifndef API_EXPORT +#define API_EXPORT __attribute__((visibility("default"))) +#endif +#endif // OHOS_DISTRIBUTED_API_VISIBILITY_H diff --git a/pasteboard/framework/framework/include/clip/clip_plugin.h b/pasteboard/framework/framework/include/clip/clip_plugin.h new file mode 100644 index 00000000..fc549ac2 --- /dev/null +++ b/pasteboard/framework/framework/include/clip/clip_plugin.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_DISTRIBUTED_DATA_PASTEBOARD_SERVICES_FRAMEWORK_CLIPS_PLUGIN_H +#define OHOS_DISTRIBUTED_DATA_PASTEBOARD_SERVICES_FRAMEWORK_CLIPS_PLUGIN_H +#include +#include +#include +#include + +#include "api/visibility.h" +namespace OHOS::MiscServices { +class API_EXPORT ClipPlugin { +public: + enum EventStatus : uint32_t { EVT_UNKNOWN, EVT_INVALID, EVT_NORMAL, EVT_BUTT }; + + struct GlobalEvent { + uint8_t version = 0; + uint8_t frameNum = 0; + uint16_t user = 0; + uint32_t seqId = 0; + uint64_t expiration = 0; + uint16_t status = EVT_UNKNOWN; + std::string deviceId; + std::string account; + std::vector addition; + uint8_t dataType = 0; + bool operator == (const GlobalEvent globalEvent) + { + return globalEvent.seqId == this->seqId && globalEvent.deviceId == this->deviceId; + } + }; + class Factory { + public: + virtual ClipPlugin *Create() = 0; + virtual bool Destroy(ClipPlugin *) = 0; + }; + static bool RegCreator(const std::string &name, Factory *factory); + static ClipPlugin *CreatePlugin(const std::string &name); + static bool DestroyPlugin(const std::string &name, ClipPlugin *plugin); + + virtual ~ClipPlugin(); + virtual int32_t SetPasteData(const GlobalEvent &event, const std::vector &data) = 0; + virtual int32_t GetPasteData(const GlobalEvent &event, std::vector &data) = 0; + virtual std::vector GetTopEvents(uint32_t topN); + virtual std::vector GetTopEvents(uint32_t topN, int32_t user); + virtual void Clear(); + virtual void Clear(int32_t user); + +private: + static std::map factories_; +}; +} // namespace OHOS::MiscServices +#endif // OHOS_DISTRIBUTED_DATA_PASTEBOARD_SERVICES_FRAMEWORK_CLIPS_PLUGIN_H diff --git a/pasteboard/framework/framework/include/common/block_object.h b/pasteboard/framework/framework/include/common/block_object.h new file mode 100644 index 00000000..285206fa --- /dev/null +++ b/pasteboard/framework/framework/include/common/block_object.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef OHOS_DISTRIBUTED_FRAMEWORK_COMMON_BLOCK_OBJECT_H +#define OHOS_DISTRIBUTED_FRAMEWORK_COMMON_BLOCK_OBJECT_H +#include +#include +namespace OHOS { +template +class BlockObject { +public: + explicit BlockObject(uint32_t interval, const T &invalid = T()) : interval_(interval), data_(invalid) + { + } + ~BlockObject() = default; + + void SetValue(T data) + { + std::lock_guard lock(mutex_); + data_ = std::move(data); + isSet_ = true; + cv_.notify_one(); + } + + T GetValue() + { + std::unique_lock lock(mutex_); + cv_.wait_for(lock, std::chrono::seconds(interval_), [this]() { return isSet_; }); + isSet_ = false; + T data = std::move(data_); + cv_.notify_one(); + return data; + } + + void SetInterval(uint32_t interval) + { + interval_ = interval; + } + +private: + uint32_t interval_; + bool isSet_ = false; + std::mutex mutex_; + std::condition_variable cv_; + T data_; +}; +} // namespace OHOS + +#endif // OHOS_DISTRIBUTED_FRAMEWORK_COMMON_BLOCK_OBJECT_H diff --git a/pasteboard/framework/framework/include/common/concurrent_map.h b/pasteboard/framework/framework/include/common/concurrent_map.h new file mode 100644 index 00000000..6b2c5780 --- /dev/null +++ b/pasteboard/framework/framework/include/common/concurrent_map.h @@ -0,0 +1,248 @@ +/* + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_DISTRIBUTED_DATA_FRAMEWORKS_COMMON_CONCURRENT_MAP_H +#define OHOS_DISTRIBUTED_DATA_FRAMEWORKS_COMMON_CONCURRENT_MAP_H +#include +#include +#include +namespace OHOS { +template +class ConcurrentMap { +public: + using key_type = typename std::map<_Key, _Tp>::key_type; + using mapped_type = typename std::map<_Key, _Tp>::mapped_type; + using value_type = typename std::map<_Key, _Tp>::value_type; + using size_type = typename std::map<_Key, _Tp>::size_type; + using reference = typename std::map<_Key, _Tp>::reference; + using const_reference = typename std::map<_Key, _Tp>::const_reference; + + ConcurrentMap() = default; + ~ConcurrentMap() + { + Clear(); + } + + ConcurrentMap(const ConcurrentMap &other) + { + operator=(std::move(other)); + } + + ConcurrentMap &operator=(const ConcurrentMap &other) noexcept + { + if (this == &other) { + return *this; + } + auto tmp = other.Clone(); + std::lock_guard lock(mutex_); + entries_ = std::move(tmp); + return *this; + } + + ConcurrentMap(ConcurrentMap &&other) noexcept + { + operator=(std::move(other)); + } + + ConcurrentMap &operator=(ConcurrentMap &&other) noexcept + { + if (this == &other) { + return *this; + } + auto tmp = other.Steal(); + std::lock_guard lock(mutex_); + entries_ = std::move(tmp); + return *this; + } + + template + bool Emplace(_Args &&... allArgs) noexcept + { + std::lock_guard lock(mutex_); + auto it = entries_.emplace(std::forward<_Args>(allArgs)...); + return it->second; + } + + std::pair Find(const key_type &key) const noexcept + { + std::lock_guard lock(mutex_); + auto it = entries_.find(key); + if (it == entries_.end()) { + return std::pair{ false, mapped_type() }; + } + + return std::pair{ true, it->second }; + } + + bool Contains(const key_type &key) const noexcept + { + std::lock_guard lock(mutex_); + return (entries_.find(key) != entries_.end()); + } + + template + bool InsertOrAssign(const key_type &key, _Obj &&obj) noexcept + { + std::lock_guard lock(mutex_); + auto it = entries_.insert_or_assign(key, std::forward<_Obj>(obj)); + return it.second; + } + + bool Insert(const key_type &key, const mapped_type &value) noexcept + { + std::lock_guard lock(mutex_); + auto it = entries_.insert(value_type{ key, value }); + return it.second; + } + + size_type Erase(const key_type &key) noexcept + { + std::lock_guard lock(mutex_); + return entries_.erase(key); + } + + void Clear() noexcept + { + std::lock_guard lock(mutex_); + return entries_.clear(); + } + + bool Empty() const noexcept + { + std::lock_guard lock(mutex_); + return entries_.empty(); + } + + size_type Size() const noexcept + { + std::lock_guard lock(mutex_); + return entries_.size(); + } + + // The action`s return true mains meet the erase condition + // The action`s return false mains not meet the erase condition + size_type EraseIf(const std::function &action) noexcept + { + if (action == nullptr) { + return 0; + } + std::lock_guard lock(mutex_); +#if __cplusplus > 201703L + auto count = std::erase_if( + entries_, [&action](value_type &value) -> bool { return action(value.first, value.second); }); +#else + auto count = entries_.size(); + for (auto it = entries_.begin(); it != entries_.end();) { + if (action((*it).first, (*it).second)) { + it = entries_.erase(it); + } else { + ++it; + } + } + count -= entries_.size(); +#endif + return count; + } + + mapped_type &operator[](const key_type &key) noexcept + { + std::lock_guard lock(mutex_); + return entries_[key]; + } + + void ForEach(const std::function &action) + { + if (action == nullptr) { + return; + } + std::lock_guard lock(mutex_); + for (auto &[key, value] : entries_) { + if (action(key, value)) { + break; + } + } + } + + // The action's return value mains that the element is keep in map or not; true mains keep, false mains remove. + bool Compute(const key_type &key, const std::function &action) + { + if (action == nullptr) { + return false; + } + std::lock_guard lock(mutex_); + auto it = entries_.find(key); + if (it == entries_.end()) { + auto result = entries_.emplace(key, mapped_type()); + it = result.second ? result.first : entries_.end(); + } + if (it == entries_.end()) { + return false; + } + if (!action(it->first, it->second)) { + entries_.erase(key); + } + return true; + } + + // The action's return value mains that the element is keep in map or not; true mains keep, false mains remove. + bool ComputeIfPresent(const key_type &key, const std::function &action) + { + if (action == nullptr) { + return false; + } + std::lock_guard lock(mutex_); + auto it = entries_.find(key); + if (it == entries_.end()) { + return false; + } + if (!action(key, it->second)) { + entries_.erase(key); + } + return true; + } + + bool ComputeIfAbsent(const key_type &key, const std::function &action) + { + if (action == nullptr) { + return false; + } + std::lock_guard lock(mutex_); + auto it = entries_.find(key); + if (it != entries_.end()) { + return false; + } + entries_.emplace(key, action(key)); + return true; + } + +private: + std::map<_Key, _Tp> Steal() noexcept + { + std::lock_guard lock(mutex_); + return std::move(entries_); + } + + std::map<_Key, _Tp> Clone() const noexcept + { + std::lock_guard lock(mutex_); + return entries_; + } + +private: + mutable std::recursive_mutex mutex_; + std::map<_Key, _Tp> entries_; +}; +} // namespace OHOS +#endif // OHOS_DISTRIBUTED_DATA_FRAMEWORKS_COMMON_CONCURRENT_MAP_H diff --git a/pasteboard/framework/framework/include/device/clip_para.h b/pasteboard/framework/framework/include/device/clip_para.h new file mode 100644 index 00000000..66fb9746 --- /dev/null +++ b/pasteboard/framework/framework/include/device/clip_para.h @@ -0,0 +1,97 @@ +/* +* Copyright (C) 2023 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef PASTE_BOARD_CLIP_PARA_H +#define PASTE_BOARD_CLIP_PARA_H + +#include +#include +#include +#include + +#include "api/visibility.h" + +namespace OHOS { +namespace MiscServices { +class API_EXPORT ClipPara { +public: + struct SendInformation { + uint64_t timeStamp = 0; + uint8_t numType = 0; + uint8_t version = 0; + uint16_t userId = 0; + uint32_t seqId = 0; + uint32_t currentIndex = 0; + }; + + constexpr static uint32_t PASTEBOARD_SEND_LEN = 26; + constexpr static uint8_t TIMESTAMP_PARA_TYPE = 0x00; + constexpr static uint8_t DATA_PARA_TYPE = 0x01; + + static ClipPara &GetInstance(); + void InitMemberVariable(); + bool HasRemoteData(); + std::string GetLastLocalSyncKey(); + std::string GetLastRemoteSyncKey(); + std::string GetLastSyncNetworkId(); + uint64_t GetLocalExpiration(); + uint64_t GetRemoteExpiration(); + std::shared_ptr GetSendInformation(); + uint32_t GetFirstStageValue(); + uint32_t GetSecondStageValue(); + bool GetPullEvent(); + bool GetPullEventResult(); + bool GetPasted(); + bool GetActiveSync(); + uint8_t GetFrameNum(); + + void SetLastLocalSyncKey(const std::string lastSyncKey); + void SetLastRemoteSyncKey(const std::string lastRemoteSyncKey); + void SetLastSyncNetworkId(const std::string lastSyncNetworkId); + void SetLocalExpiration(const uint64_t expiration); + void SetRemoteExpiration(const uint64_t remoteExpiration); + void SetSendInformation(const ClipPara::SendInformation &senderInformation); + void SetFirstStageValue(const uint32_t firstStageValue); + void SetSecondStageValue(const uint32_t secondStageValue); + void SetPullEvent(const bool isPullEvent); + void SetPullEventResult(const bool isPullEventResult); + void SetPasted(const bool isPasted); + void UpdateStageValue(const uint64_t &expiration, bool isPasting); + void SetActiveSync(const bool activeSync); + void SetFrameNum(const uint8_t frameNum); + +private: + ClipPara(); + ~ClipPara() = default; + static constexpr uint32_t MAX_STAGE_VALUE = 2; + static constexpr uint32_t MIN_STAGE_VALUE = 0; + std::mutex mutex_; + std::string lastLocalSyncKey_; + std::string lastRemoteSyncKey_; + std::string lastSyncNetworkId_; + std::atomic isPullEvent_ = false; + std::atomic isPullEventResult_ = false; + std::atomic isPasted_ = false; + std::atomic activeSync_ = false; + std::atomic frameNum_ = 0; + std::atomic localExpiration_ = 0; + std::atomic remoteExpiration_ = 0; + std::atomic firstStageValue_ = 2; + std::atomic secondStageValue_ = 0; + std::shared_ptr sendInformation_; +}; +} // namespace MiscServices +} // namespace OHOS +#endif // PASTE_BOARD_CLIP_PARA_H \ No newline at end of file diff --git a/pasteboard/framework/framework/include/device/dev_manager.h b/pasteboard/framework/framework/include/device/dev_manager.h new file mode 100644 index 00000000..fefbabe2 --- /dev/null +++ b/pasteboard/framework/framework/include/device/dev_manager.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PASTE_BOARD_DEV_MANAGER_H +#define PASTE_BOARD_DEV_MANAGER_H + +#include +#include + +#include "api/visibility.h" + +namespace OHOS { +namespace MiscServices { +class API_EXPORT DevManager { +public: + static DevManager &GetInstance(); + std::vector GetNetworkIds(); + std::vector GetOldNetworkIds(); + int32_t Init(); + void OnReady(); + void Online(const std::string &networkId); + void Offline(const std::string &networkId); + void UnregisterDevCallback(); + +private: + using Function = bool (*)(); + DevManager(); + ~DevManager() = default; + void RetryInBlocking(Function func) const; +}; +} // namespace MiscServices +} // namespace OHOS +#endif // PASTE_BOARD_DEV_MANAGER_H diff --git a/pasteboard/framework/framework/include/device/dev_profile.h b/pasteboard/framework/framework/include/device/dev_profile.h new file mode 100644 index 00000000..c31c21fd --- /dev/null +++ b/pasteboard/framework/framework/include/device/dev_profile.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PASTE_BOARD_DEV_PROFILE_H +#define PASTE_BOARD_DEV_PROFILE_H + +#include +#include +#include "api/visibility.h" + +#ifdef PB_DEVICE_INFO_MANAGER_ENABLE +#include "distributed_device_profile_client.h" +#endif // PB_DEVICE_INFO_MANAGER_ENABLE + +namespace OHOS { +namespace MiscServices { +class API_EXPORT DevProfile { +public: + static DevProfile &GetInstance(); + void GetEnabledStatus(const std::string &networkId, std::string &enabledStatus); + void Init(); + void OnReady(); + void PutEnabledStatus(const std::string &enabledStatus); + void GetRemoteDeviceVersion(const std::string &networkId, uint32_t &deviceVersion); + void SubscribeProfileEvent(const std::string &networkId); + void UnSubscribeProfileEvent(const std::string &networkId); + void UnsubscribeAllProfileEvents(); + bool GetLocalEnable(); + static constexpr const uint32_t FIRST_VERSION = 4; + #ifdef PB_DEVICE_INFO_MANAGER_ENABLE + class PasteboardProfileEventCallback : public DeviceProfile::IProfileEventCallback { + public: + void OnSyncCompleted(const DeviceProfile::SyncResult &syncResults) override; + void OnProfileChanged(const DeviceProfile::ProfileChangeNotification &changeNotification) override; + }; + #endif + +private: + DevProfile(); + ~DevProfile() = default; + static void ParameterChange(const char *key, const char *value, void *context); + std::mutex callbackMutex_; + bool localEnable_ = false; + + #ifdef PB_DEVICE_INFO_MANAGER_ENABLE + std::map> callback_; + #endif // PB_DEVICE_INFO_MANAGER_ENABLE + +}; +} // namespace MiscServices +} // namespace OHOS +#endif // PASTE_BOARD_DEV_PROFILE_H diff --git a/pasteboard/framework/framework/include/device/distributed_module_config.h b/pasteboard/framework/framework/include/device/distributed_module_config.h new file mode 100644 index 00000000..e0f84671 --- /dev/null +++ b/pasteboard/framework/framework/include/device/distributed_module_config.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PASTE_BOARD_DISTRIBUTE_MODULE_CONFIG_H +#define PASTE_BOARD_DISTRIBUTE_MODULE_CONFIG_H + +#include "api/visibility.h" +#include + +namespace OHOS { +namespace MiscServices { +class API_EXPORT DistributedModuleConfig { +public: + using Observer = std::function; + static bool IsOn(); + static void Watch(Observer observer); + static void ForceNotify(); + static void Notify(); + static void GetDeviceNum(); +private: + static bool GetEnabledStatus(); + static Observer observer_; + static bool status_; + static size_t deviceNums_; +}; +} // namespace MiscServices +} // namespace OHOS +#endif // PASTE_BOARD_DISTRIBUTE_MODULE_CONFIG_H diff --git a/pasteboard/framework/framework/include/device/dm_adapter.h b/pasteboard/framework/framework/include/device/dm_adapter.h new file mode 100644 index 00000000..5b1959d8 --- /dev/null +++ b/pasteboard/framework/framework/include/device/dm_adapter.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_PASTEBOARD_SERVICES_DEVICE_DM_ADAPTER_H +#define OHOS_PASTEBOARD_SERVICES_DEVICE_DM_ADAPTER_H +#include +#include + +#include "api/visibility.h" +#include "common/concurrent_map.h" +#ifdef PB_DEVICE_MANAGER_ENABLE +#include "dm_device_info.h" +#endif + +namespace OHOS::MiscServices { +#ifdef PB_DEVICE_MANAGER_ENABLE +using namespace OHOS::DistributedHardware; +#endif +class API_EXPORT DMAdapter { +public: + static constexpr size_t MAX_ID_LEN = 64; + static constexpr size_t RESULT_OK = 0; + class DMObserver { + public: + virtual void Online(const std::string &device) = 0; + virtual void Offline(const std::string &device) = 0; + virtual void OnReady(const std::string &device) = 0; + }; + static DMAdapter &GetInstance(); + bool Initialize(const std::string &pkgName); + const std::string &GetLocalDeviceUdid(); + const std::string GetLocalNetworkId(); + std::string GetUdidByNetworkId(const std::string &networkId); + #ifdef PB_DEVICE_MANAGER_ENABLE + int32_t GetRemoteDeviceInfo(const std::string &networkId, DmDeviceInfo &remoteDevice); + #endif + std::string GetDeviceName(const std::string &networkId); + void Register(DMObserver *observer); + void Unregister(DMObserver *observer); + +private: + static constexpr const char *NAME_EX = "dm_adapter"; + static constexpr const char *DEVICE_INVALID_NAME = "unknown"; + DMAdapter(); + ~DMAdapter(); + + std::string pkgName_; + const std::string invalidDeviceUdid_{}; + const std::string invalidNetworkId_{}; + const std::string invalidUdid_{}; + mutable std::mutex mutex_{}; + std::string localDeviceUdid_{}; + ConcurrentMap observers_; +}; +} // namespace OHOS::MiscServices +#endif // OHOS_PASTEBOARD_SERVICES_DEVICE_DM_ADAPTER_H diff --git a/pasteboard/framework/framework/include/device/para_handle.h b/pasteboard/framework/framework/include/device/para_handle.h new file mode 100644 index 00000000..79f0d1cb --- /dev/null +++ b/pasteboard/framework/framework/include/device/para_handle.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PASTE_BOARD_PARA_HANDLE_H +#define PASTE_BOARD_PARA_HANDLE_H +#include + +#include "api/visibility.h" +#include "parameter.h" + +namespace OHOS { +namespace MiscServices { +class API_EXPORT ParaHandle { +public: + static constexpr const char *DISTRIBUTED_PASTEBOARD_ENABLED_KEY = "persist.pasteboard." + "distributedPasteboardEnabled"; + static ParaHandle &GetInstance(); + std::string GetEnabledStatus() const; + void Init(); + void WatchEnabledStatus(ParameterChgPtr ptr) const; + +private: + static constexpr const char *DISTRIBUTED_PASTEBOARD_ENABLED_DEFAULT_VALUE = "true"; + static constexpr int CONFIG_LEN = 10; + ParaHandle(); + virtual ~ParaHandle() = default; +}; +} // namespace MiscServices +} // namespace OHOS +#endif // PASTE_BOARD_PARA_HANDLE_H diff --git a/pasteboard/framework/framework/include/serializable/serializable.h b/pasteboard/framework/framework/include/serializable/serializable.h new file mode 100644 index 00000000..4ea230b3 --- /dev/null +++ b/pasteboard/framework/framework/include/serializable/serializable.h @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_DISTRIBUTED_SERIALIZABLE_SERIALIZABLE_H +#define OHOS_DISTRIBUTED_SERIALIZABLE_SERIALIZABLE_H +#include +#include + +#include "api/visibility.h" +#ifndef JSON_NOEXCEPTION +#define JSON_NOEXCEPTION +#endif +#include "cJSON.h" +namespace OHOS { +namespace DistributedData { +#ifndef GET_NAME +#define GET_NAME(value) #value +#endif +struct Serializable { +public: + using json = cJSON; + API_EXPORT json Marshall() const; + template + static std::string Marshall(T &values) + { + json *root; + SetValue(*root, values); + return cJSON_PrintUnformatted(root); + } + + API_EXPORT bool Unmarshall(const std::string &jsonStr); + template + static bool Unmarshall(const std::string &body, T &values) + { + return GetValue(ToJson(body), "", values); + } + API_EXPORT static json ToJson(const std::string &jsonStr); + virtual bool Marshal(json &node) const = 0; + virtual bool Unmarshal(const json &node) = 0; + API_EXPORT static bool GetValue(const json &node, const std::string &name, std::string &value); + API_EXPORT static bool GetValue(const json &node, const std::string &name, uint32_t &value); + API_EXPORT static bool GetValue(const json &node, const std::string &name, int32_t &value); + API_EXPORT static bool GetValue(const json &node, const std::string &name, int64_t &value); + API_EXPORT static bool GetValue(const json &node, const std::string &name, bool &value); + API_EXPORT static bool GetValue(const json &node, const std::string &name, std::vector &value); + API_EXPORT static bool GetValue(const json &node, const std::string &name, Serializable &value); + API_EXPORT static bool SetValue( + json &node, const std::string &value, const std::string &name = "", const bool &isObject = true); + API_EXPORT static bool SetValue( + json &node, const uint32_t &value, const std::string &name = "", const bool &isObject = true); + API_EXPORT static bool SetValue( + json &node, const int32_t &value, const std::string &name = "", const bool &isObject = true); + API_EXPORT static bool SetValue( + json &node, const int64_t &value, const std::string &name = "", const bool &isObject = true); + API_EXPORT static bool SetValue( + json &node, const bool &value, const std::string &name = "", const bool &isObject = true); + API_EXPORT static bool SetValue( + json &node, const std::vector &value, const std::string &name = "", const bool &isObject = true); + API_EXPORT static bool SetValue( + json &node, const Serializable &value, const std::string &name = "", const bool &isObject = true); + +protected: + API_EXPORT ~Serializable() = default; + + template + static bool GetValue(const json &node, const std::string &name, T *&value) + { + auto &subNode = GetSubNode(node, name); + if (cJSON_IsNull(&subNode)) { + return false; + } + value = new (std::nothrow) T(); + if (value == nullptr) { + return false; + } + bool result = GetValue(subNode, "", *value); + if (!result) { + delete value; + value = nullptr; + } + return result; + } + template + static bool GetValue(const json &node, const std::string &name, std::vector &values) + { + auto &subNode = GetSubNode(node, name); + if (cJSON_IsNull(&subNode) || !cJSON_IsArray(&subNode)) { + return false; + } + bool result = true; + values.resize(cJSON_GetArraySize(&subNode)); + for (int i = 0; i < cJSON_GetArraySize(&subNode); ++i) { + result = GetValue(*cJSON_GetArrayItem(&subNode, i), "", values[i]) && result; + } + return result; + } + + template + static bool SetValue( + json &node, const std::vector &values, const std::string &name = "", const bool &isObject = true) + { + bool result = true; + int i = 0; + auto subNode = cJSON_CreateArray(); + for (const auto &value : values) { + json *item = cJSON_CreateNull(); + result = SetValue(*item, value, "", false) && result; + cJSON_AddItemToArray(subNode, item); + i++; + } + + if (!isObject) { + node = *subNode; + delete subNode; + return result; + } + SetValueCommon(node, *subNode, name); + return result; + } + + API_EXPORT static const json &GetSubNode(const json &node, const std::string &name); + static void SetValueCommon(json &node, json &subNode, const std::string &name) + { + if (!cJSON_IsObject(&node)) { + node = *cJSON_CreateObject(); + } + cJSON_AddItemToObject(&node, name.c_str(), &subNode); + } +}; +} // namespace DistributedData +} // namespace OHOS +#endif // OHOS_DISTRIBUTED_SERIALIZABLE_SERIALIZABLE_H diff --git a/pasteboard/framework/framework/serializable/serializable.cpp b/pasteboard/framework/framework/serializable/serializable.cpp new file mode 100644 index 00000000..65598709 --- /dev/null +++ b/pasteboard/framework/framework/serializable/serializable.cpp @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "serializable/serializable.h" +namespace OHOS { +namespace DistributedData { +Serializable::json Serializable::Marshall() const +{ + json root; + Marshal(root); + return root; +} + +bool Serializable::Unmarshall(const std::string &jsonStr) +{ + json *jsonObj = cJSON_Parse(jsonStr.c_str()); + if (jsonObj == nullptr) { + // if the string size is less than 1, means the string is invalid. + if (jsonStr.empty()) { + return false; + } + jsonObj = cJSON_Parse(jsonStr.substr(1).c_str()); // drop first char to adapt A's value; + if (jsonObj == nullptr) { + return false; + } + } + return Unmarshal(*jsonObj); +} + +Serializable::json Serializable::ToJson(const std::string &jsonStr) +{ + json *jsonObj = cJSON_Parse(jsonStr.c_str()); + if (jsonObj == nullptr) { + // if the string size is less than 1, means the string is invalid. + if (jsonStr.empty()) { + return *cJSON_CreateNull(); + } + jsonObj = cJSON_Parse(jsonStr.substr(1).c_str()); // drop first char to adapt A's value; + if (jsonObj == nullptr) { + return *cJSON_CreateNull(); + } + } + return *jsonObj; +} + +bool Serializable::GetValue(const json &node, const std::string &name, std::string &value) +{ + auto &subNode = GetSubNode(node, name); + if (cJSON_IsNull(&subNode) || !cJSON_IsString(&subNode)) { + return false; + } + value = cJSON_GetStringValue(&subNode); + return true; +} + +bool Serializable::GetValue(const json &node, const std::string &name, uint32_t &value) +{ + auto &subNode = GetSubNode(node, name); + if (cJSON_IsNull(&subNode) || !cJSON_IsNumber(&subNode)) { + return false; + } + value = cJSON_GetNumberValue(&subNode); + return true; +} + +bool Serializable::GetValue(const json &node, const std::string &name, int32_t &value) +{ + auto &subNode = GetSubNode(node, name); + if (cJSON_IsNull(&subNode) || !cJSON_IsNumber(&subNode)) { + return false; + } + value = cJSON_GetNumberValue(&subNode); + return true; +} + +bool Serializable::GetValue(const json &node, const std::string &name, int64_t &value) +{ + auto &subNode = GetSubNode(node, name); + if (cJSON_IsNull(&subNode) || !cJSON_IsNumber(&subNode)) { + return false; + } + value = cJSON_GetNumberValue(&subNode); + return true; +} + +bool Serializable::GetValue(const json &node, const std::string &name, bool &value) +{ + auto &subNode = GetSubNode(node, name); + if (cJSON_IsNull(&subNode) || !cJSON_IsBool(&subNode)) { + return false; + } + value = cJSON_IsTrue(&subNode); + return true; +} + +bool Serializable::GetValue(const json &node, const std::string &name, std::vector &value) +{ + auto &subNode = GetSubNode(node, name); + if (cJSON_IsNull(&subNode) || !cJSON_IsArray(&subNode)) { + return false; + } + for (int i = 0; i < cJSON_GetArraySize(&subNode); i++) { + value.emplace_back(cJSON_GetNumberValue(cJSON_GetArrayItem(&subNode, i))); + } + return true; +} + +bool Serializable::GetValue(const json &node, const std::string &name, Serializable &value) +{ + auto &subNode = GetSubNode(node, name); + if (cJSON_IsNull(&subNode) || !cJSON_IsObject(&subNode)) { + return false; + } + return value.Unmarshal(subNode); +} + +bool Serializable::SetValue(json &node, const std::string &value, const std::string &name, const bool &isObject) +{ + json *subNode = cJSON_CreateString(value.c_str()); + if (!isObject) { + node = *subNode; + delete subNode; + return true; + } + SetValueCommon(node, *subNode, name); + return true; +} + +bool Serializable::SetValue(json &node, const uint32_t &value, const std::string &name, const bool &isObject) +{ + json *subNode = cJSON_CreateNumber(value); + if (!isObject) { + node = *subNode; + delete subNode; + return true; + } + SetValueCommon(node, *subNode, name); + return true; +} + +bool Serializable::SetValue(json &node, const int32_t &value, const std::string &name, const bool &isObject) +{ + json *subNode = cJSON_CreateNumber(value); + if (!isObject) { + node = *subNode; + delete subNode; + return true; + } + SetValueCommon(node, *subNode, name); + return true; +} + +bool Serializable::SetValue(json &node, const int64_t &value, const std::string &name, const bool &isObject) +{ + json *subNode = cJSON_CreateNumber(value); + if (!isObject) { + node = *subNode; + delete subNode; + return true; + } + SetValueCommon(node, *subNode, name); + return true; +} + +bool Serializable::SetValue(json &node, const bool &value, const std::string &name, const bool &isObject) +{ + json *subNode = cJSON_CreateBool(value); + if (!isObject) { + node = *subNode; + delete subNode; + return true; + } + SetValueCommon(node, *subNode, name); + return true; +} + +bool Serializable::SetValue( + json &node, const std::vector &value, const std::string &name, const bool &isObject) +{ + json *subNode = cJSON_CreateArray(); + for (const uint8_t &item : value) { + cJSON_AddItemToArray(subNode, cJSON_CreateNumber(item)); + } + if (!isObject) { + node = *subNode; + delete subNode; + return true; + } + SetValueCommon(node, *subNode, name); + return true; +} + +bool Serializable::SetValue(json &node, const Serializable &value, const std::string &name, const bool &isObject) +{ + json *subNode = cJSON_CreateNull(); + if (!value.Marshal(*subNode)) { + return false; + } + if (!isObject) { + node = *subNode; + delete subNode; + return true; + } + SetValueCommon(node, *subNode, name); + return true; +} + +const Serializable::json &Serializable::GetSubNode(const json &node, const std::string &name) +{ + static const json *jsonNull = cJSON_CreateNull(); + if (cJSON_IsNull(&node)) { + return *jsonNull; + } + + if (name.empty()) { + return node; + } + if (!cJSON_HasObjectItem(&node, name.c_str())) { + return *jsonNull; + } + return *cJSON_GetObjectItem(&node, name.c_str()); +} +} // namespace DistributedData +} // namespace OHOS \ No newline at end of file diff --git a/pasteboard/framework/framework/test/dm_adapter_test.cpp b/pasteboard/framework/framework/test/dm_adapter_test.cpp new file mode 100644 index 00000000..02120bfd --- /dev/null +++ b/pasteboard/framework/framework/test/dm_adapter_test.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "device/dm_adapter.h" + +#include +namespace OHOS::MiscServices { +using namespace testing::ext; + +class DMAdapterTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void DMAdapterTest::SetUpTestCase(void) +{ +} + +void DMAdapterTest::TearDownTestCase(void) +{ +} + +void DMAdapterTest::SetUp(void) +{ +} + +void DMAdapterTest::TearDown(void) +{ +} + +/** +* @tc.name: GetLocalDeviceUdid +* @tc.desc: Get the local device udid. +* @tc.type: FUNC +*/ +HWTEST_F(DMAdapterTest, GetLocalDeviceUdid, TestSize.Level0) +{ + auto &udid = DMAdapter::GetInstance().GetLocalDeviceUdid(); + ASSERT_FALSE(udid.empty()); +} +} diff --git a/pasteboard/framework/innerkits/BUILD.gn b/pasteboard/framework/innerkits/BUILD.gn new file mode 100644 index 00000000..87d20b14 --- /dev/null +++ b/pasteboard/framework/innerkits/BUILD.gn @@ -0,0 +1,84 @@ +# Copyright (c) 2023 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") +import("//foundation/distributeddatamgr/pasteboard/pasteboard.gni") + +config("pasteboard_client_config") { + visibility = [ ":*" ] + visibility += [ "//foundation/distributeddatamgr/pasteboard/test/fuzztest/pasteboardclient_fuzzer/*" ] + include_dirs = [ + "include", + "${pasteboard_service_path}/core/include", + "${pasteboard_service_path}/dfx/src", + "${pasteboard_service_path}/zidl/include", + "${pasteboard_utils_path}/native/include", + "//commonlibrary/c_utils/base/include", + "//foundation/distributeddatamgr/pasteboard/framework/framework/include", + "//foundation/distributeddatamgr/pasteboard/framework/tlv", + "//foundation/distributeddatamgr/pasteboard/framework/uri", + "//foundation/filemanagement/app_file_service/interfaces/innerkits/remote_file_share/native", + ] +} + +ohos_shared_library("pasteboard_client") { + branch_protector_ret = "pac_ret" + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + } + sources = [ + "${pasteboard_service_path}/dfx/src/hiview_adapter.cpp", + "${pasteboard_service_path}/zidl/src/pasteboard_observer_stub.cpp", + "${pasteboard_service_path}/zidl/src/pasteboard_service_proxy.cpp", + "src/paste_data.cpp", + "src/paste_data_record.cpp", + "src/pasteboard_client.cpp", + "src/pasteboard_load_callback.cpp", + "src/pasteboard_observer.cpp", + "src/pasteboard_web_controller.cpp", + ] + + cflags_cc = [ + "-fstack-protector", + "-D_FORTIFY_SOURCE=2", + "-O2", + ] + + configs = [ ":pasteboard_client_config" ] + public_configs = [ ":pasteboard_client_config" ] + deps = [ + "${pasteboard_root_path}/framework/tlv:pasteboard_tlv", + "${pasteboard_root_path}/framework/uri:pasteboard_uri", + ] + + external_deps = [ + "ability_base:want", + "ability_base:zuri", + "ability_runtime:wantagent_innerkits", + "app_file_service:fileuri_native", + "c_utils:utils", + "hilog:libhilog", + "hisysevent:libhisysevent", + "hitrace:hitrace_meter", + "image_framework:image_native", + "ipc:ipc_core", + "samgr:samgr_proxy", + "time_service:time_client", + ] + + subsystem_name = "distributeddatamgr" + innerapi_tags = [ "platformsdk" ] + part_name = "pasteboard" +} diff --git a/pasteboard/framework/innerkits/include/paste_data.h b/pasteboard/framework/innerkits/include/paste_data.h new file mode 100644 index 00000000..d96129f2 --- /dev/null +++ b/pasteboard/framework/innerkits/include/paste_data.h @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2021-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef PASTE_BOARD_DATA_H +#define PASTE_BOARD_DATA_H + +#include +#include +#include +#include +#include +#include + +#include "paste_data_record.h" +#include "pasteboard_hilog.h" +#include "tlv_object.h" +#include "uri.h" +#include "want.h" +#include "want_params.h" + +namespace OHOS { +namespace MiscServices { +enum ShareOption : int32_t { InApp = 0, LocalDevice, CrossDevice }; +struct PasteDataProperty : public TLVObject { + PasteDataProperty() = default; + ~PasteDataProperty(); + explicit PasteDataProperty(const PasteDataProperty &property); + PasteDataProperty& operator=(const PasteDataProperty &property); + AAFwk::WantParams additions; + std::vector mimeTypes; + std::string tag; + std::int64_t timestamp; + bool localOnly; + ShareOption shareOption; + uint32_t tokenId = 0; + bool isRemote = false; + std::string bundleName; + std::string setTime; + + bool Encode(std::vector &buffer) override; + bool Decode(const std::vector &buffer) override; + bool DecodeTag(const std::vector &buffer); + size_t Count() override; +}; + +class PasteData : public TLVObject { +public: + static constexpr const std::uint32_t MAX_RECORD_NUM = 512; + PasteData(); + ~PasteData(); + explicit PasteData(const PasteData &data); + PasteData& operator=(const PasteData &data); + explicit PasteData(std::vector> records); + + void AddHtmlRecord(const std::string &html); + void AddKvRecord(const std::string &mimeType, const std::vector &arrayBuffer); + void AddPixelMapRecord(std::shared_ptr pixelMap); + void AddTextRecord(const std::string &text); + void AddUriRecord(const OHOS::Uri &uri); + void AddWantRecord(std::shared_ptr want); + void AddRecord(std::shared_ptr record); + void AddRecord(PasteDataRecord &record); + std::vector GetMimeTypes(); + std::shared_ptr GetPrimaryHtml(); + std::shared_ptr GetPrimaryPixelMap(); + std::shared_ptr GetPrimaryText(); + std::shared_ptr GetPrimaryUri(); + std::shared_ptr GetPrimaryMimeType(); + std::shared_ptr GetPrimaryWant(); + std::shared_ptr GetRecordAt(std::size_t index); + std::size_t GetRecordCount(); + bool RemoveRecordAt(std::size_t number); + bool ReplaceRecordAt(std::size_t number, std::shared_ptr record); + bool HasMimeType(const std::string &mimeType); + PasteDataProperty GetProperty() const; + void SetProperty(const PasteDataProperty &property); + ShareOption GetShareOption(); + void SetShareOption(ShareOption shareOption); + uint32_t GetTokenId(); + void SetTokenId(uint32_t tokenId); + std::vector> AllRecords() const; + bool IsDraggedData() const; + void SetDraggedDataFlag(bool isDraggedData); + bool IsLocalPaste() const; + void SetLocalPasteFlag(bool isLocalPaste); + + void SetBundleName(const std::string &bundleName); + std::string GetBundleName() const; + void SetOrginAuthority(const std::string &bundleName); + std::string GetOrginAuthority() const; + void SetRemote(bool isRemote); + bool IsRemote(); + void SetTime(const std::string &time); + std::string GetTime(); + void SetTag(std::string &tag); + std::string GetTag(); + void SetAdditions(AAFwk::WantParams &additions); + void SetAddition(const std::string &key, AAFwk::IInterface *value); + void SetLocalOnly(bool localOnly); + bool GetLocalOnly(); + + bool Encode(std::vector &buffer) override; + bool Decode(const std::vector &buffer) override; + size_t Count() override; + bool WriteUriFd(MessageParcel &parcel, UriHandler &uriHandler, bool isClient = true); + bool ReadUriFd(MessageParcel &parcel, UriHandler &uriHandler); + void ReplaceShareUri(int32_t userId); + + bool IsValid() const; + void SetInvalid(); + + static void ShareOptionToString(ShareOption shareOption, std::string &out); + static std::string sharePath; + static std::string WEBVIEW_PASTEDATA_TAG; + static const std::string DISTRIBUTEDFILES_TAG; + static const std::string PATH_SHARE; + static const std::string FILE_SCHEME_PREFIX; + static const std::string IMG_LOCAL_URI; + static const std::string SHARE_PATH_PREFIX; + static const std::string SHARE_PATH_PREFIX_ACCOUNT; + static const std::string REMOTE_FILE_SIZE; + +private: + void RefreshMimeProp(); + + PasteDataProperty props_; + std::vector> records_; + std::string orginAuthority_; + bool valid_ = true; + bool isDraggedData_ = false; + bool isLocalPaste_ = false; // local in app paste +}; +} // namespace MiscServices +} // namespace OHOS +#endif // PASTE_BOARD_DATA_H diff --git a/pasteboard/framework/innerkits/include/paste_data_record.h b/pasteboard/framework/innerkits/include/paste_data_record.h new file mode 100644 index 00000000..4273e377 --- /dev/null +++ b/pasteboard/framework/innerkits/include/paste_data_record.h @@ -0,0 +1,150 @@ +/* + * Copyright (C) 2021-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PASTE_BOARD_RECORD_H +#define PASTE_BOARD_RECORD_H + +#include +#include + +#include "message_parcel.h" +#include "pixel_map.h" +#include "string_ex.h" +#include "tlv_object.h" +#include "uri.h" +#include "uri_handler.h" +#include "want.h" + +namespace OHOS { +namespace MiscServices { +namespace { +const std::string MIMETYPE_PIXELMAP = "pixelMap"; +const std::string MIMETYPE_TEXT_HTML = "text/html"; +const std::string MIMETYPE_TEXT_PLAIN = "text/plain"; +const std::string MIMETYPE_TEXT_URI = "text/uri"; +const std::string MIMETYPE_TEXT_WANT = "text/want"; +} // namespace + +enum ResultCode : int32_t { OK = 0, IPC_NO_DATA, IPC_ERROR }; + +class MineCustomData : public TLVObject { +public: + MineCustomData() = default; + std::map> GetItemData(); + void AddItemData(const std::string &mimeType, const std::vector &arrayBuffer); + bool Encode(std::vector &buffer) override; + bool Decode(const std::vector &buffer) override; + size_t Count() override; + +private: + std::map> itemData_; +}; + +class FileDescriptor { +public: + FileDescriptor() = default; + ~FileDescriptor(); + void SetFd(int32_t fd); + int32_t GetFd() const; + +private: + int32_t fd_ = -1; +}; + +class PasteDataRecord : public TLVObject { +public: + PasteDataRecord(); + ~PasteDataRecord(); + PasteDataRecord(const PasteDataRecord &record); + PasteDataRecord(std::string mimeType, std::shared_ptr htmlText, + std::shared_ptr want, std::shared_ptr plainText, + std::shared_ptr uri); + + static std::shared_ptr NewHtmlRecord(const std::string &htmlText); + static std::shared_ptr NewWantRecord(std::shared_ptr want); + static std::shared_ptr NewPlaintTextRecord(const std::string &text); + static std::shared_ptr NewPixelMapRecord(std::shared_ptr pixelMap); + static std::shared_ptr NewUriRecord(const OHOS::Uri &uri); + static std::shared_ptr NewKvRecord( + const std::string &mimeType, const std::vector &arrayBuffer); + + bool isConvertUriFromRemote = false; + std::string GetMimeType() const; + std::shared_ptr GetHtmlText() const; + std::shared_ptr GetPlainText() const; + std::shared_ptr GetPixelMap() const; + void ClearPixelMap(); + std::shared_ptr GetUri() const; + void SetUri(std::shared_ptr uri); + std::shared_ptr GetOrginUri() const; + std::shared_ptr GetWant() const; + std::shared_ptr GetCustomData() const; + + std::string ConvertToText() const; + + bool Encode(std::vector &buffer) override; + bool Decode(const std::vector &buffer) override; + size_t Count() override; + bool WriteFd(MessageParcel &parcel, UriHandler &uriHandler, bool isClient); + bool ReadFd(MessageParcel &parcel, UriHandler &uriHandler); + bool NeedFd(const UriHandler &uriHandler); + void ReplaceShareUri(int32_t userId); + void SetConvertUri(const std::string &value); + std::string GetConvertUri() const; + void SetGrantUriPermission(bool hasPermission); + bool HasGrantUriPermission(); + + class Builder { + public: + explicit Builder(const std::string &mimeType); + Builder &SetHtmlText(std::shared_ptr htmlText); + Builder &SetWant(std::shared_ptr want); + Builder &SetPlainText(std::shared_ptr plainText); + Builder &SetUri(std::shared_ptr uri); + Builder &SetPixelMap(std::shared_ptr pixelMap); + Builder &SetCustomData(std::shared_ptr customData); + Builder &SetMimeType(std::string mimeType); + std::shared_ptr Build(); + + private: + std::shared_ptr record_ = nullptr; + }; + +private: + inline static bool CheckResult(ResultCode resultCode) + { + return resultCode == ResultCode::OK; + } + std::string GetPassUri(); + static std::shared_ptr Vector2PixelMap(std::vector &value); + static std::vector PixelMap2Vector(std::shared_ptr &pixelMap); + + std::string mimeType_; + std::shared_ptr htmlText_; + std::shared_ptr want_; + std::shared_ptr plainText_; + std::shared_ptr uri_; + std::string convertUri_; + std::shared_ptr pixelMap_; + std::shared_ptr customData_; + bool hasGrantUriPermission_ = false; + std::shared_ptr fd_; + using Func = std::function &buffer, TLVHead &head)>; + std::map decodeMap; + void InitDecodeMap(); +}; +} // namespace MiscServices +} // namespace OHOS +#endif // PASTE_BOARD_RECORD_H diff --git a/pasteboard/framework/innerkits/include/pasteboard_client.h b/pasteboard/framework/innerkits/include/pasteboard_client.h new file mode 100644 index 00000000..6f682ccf --- /dev/null +++ b/pasteboard/framework/innerkits/include/pasteboard_client.h @@ -0,0 +1,282 @@ +/* + * Copyright (c) 2021-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PASTE_BOARD_CLIENT_H +#define PASTE_BOARD_CLIENT_H + +#include +#include +#include +#include "i_pasteboard_service.h" +#include "paste_data.h" +#include "paste_data_record.h" +#include "pasteboard_observer.h" +#include "want.h" + +namespace OHOS { +namespace MiscServices { +class PasteboardSaDeathRecipient : public IRemoteObject::DeathRecipient { +public: + explicit PasteboardSaDeathRecipient(); + ~PasteboardSaDeathRecipient() = default; + void OnRemoteDied(const wptr &object) override; + +private: + DISALLOW_COPY_AND_MOVE(PasteboardSaDeathRecipient); +}; +class PasteboardClient : public DelayedSingleton { + DECLARE_DELAYED_SINGLETON(PasteboardClient); + +public: + DISALLOW_COPY_AND_MOVE(PasteboardClient); + + /** + * CreateHtmlTextRecord + * @descrition Create Html Text Record. + * @param std::string text. + * @return PasteDataRecord. + */ + std::shared_ptr CreateHtmlTextRecord(const std::string &text); + + /** + * CreatePlainTextRecord + * @descrition Create Plaint Text Record. + * @param std::string text. + * @return PasteDataRecord. + */ + std::shared_ptr CreatePlainTextRecord(const std::string &text); + + /** + * CreatePixelMapRecord + * @descrition Create PixelMap Record. + * @param OHOS::Media::PixelMap pixelMap. + * @return PasteDataRecord. + */ + std::shared_ptr CreatePixelMapRecord(std::shared_ptr pixelMap); + + /** + * CreateUriRecord + * @descrition Create Uri Text Record. + * @param OHOS::Uri uri. + * @return PasteDataRecord. + */ + std::shared_ptr CreateUriRecord(const OHOS::Uri &uri); + + /** + * CreateWantRecord + * @descrition Create Plaint Want Record. + * @param OHOS::AAFwk::Want want. + * @return PasteDataRecord. + */ + std::shared_ptr CreateWantRecord(std::shared_ptr want); + + /** + * CreateKvRecord + * @descrition Create Kv Record. + * @param std::string mimeType + * @param std::vector arrayBuffer + * @return PasteDataRecord. + */ + std::shared_ptr CreateKvRecord( + const std::string &mimeType, const std::vector &arrayBuffer); + + /** + * CreateHtmlData + * @descrition Create Html Paste Data. + * @param std::string text . + * @return PasteData. + */ + std::shared_ptr CreateHtmlData(const std::string &htmlText); + + /** + * CreatePlainTextData + * @descritionCreate Plain Text Paste Data. + * @param std::string text . + * @return PasteData. + */ + std::shared_ptr CreatePlainTextData(const std::string &text); + + /** + * CreatePixelMapData + * @descrition Create PixelMap Paste Data. + * @param OHOS::Media::PixelMap pixelMap . + * @return PasteData. + */ + std::shared_ptr CreatePixelMapData(std::shared_ptr pixelMap); + + /** + * CreateUriData + * @descrition Create Uri Paste Data. + * @param OHOS::Uri uri . + * @return PasteData. + */ + std::shared_ptr CreateUriData(const OHOS::Uri &uri); + + /** + * CreateWantData + * @descrition Create Want Paste Data. + * @param OHOS::AAFwk::Want want . + * @return PasteData. + */ + std::shared_ptr CreateWantData(std::shared_ptr want); + + /** + * CreateKvData + * @descrition Create Kv Paste Data. + * @param std::string mimeType + * @param std::vector arrayBuffer + * @return PasteData. + */ + std::shared_ptr CreateKvData(const std::string &mimeType, const std::vector &arrayBuffer); + + /** + * GetPasteData + * @descrition get paste data from the pasteboard. + * @param pasteData the object of the PasteDate. + * @return int32_t. + */ + int32_t GetPasteData(PasteData &pasteData); + + /** + * HasPasteData + * @descrition check paste data exist in the pasteboard. + * @return bool. True exists, false does not exist + */ + bool HasPasteData(); + + /** + * Clear + * @descrition Clear Current pasteboard data. + * @return void. + */ + void Clear(); + + /** + * SetPasteData + * @descrition set paste data to the pasteboard. + * @param pasteData the object of the PasteDate. + * @return int32_t. + */ + int32_t SetPasteData(PasteData &pasteData); + + /** + * IsRemoteData + * @descrition check if remote data. + * @return bool. True is remote data, else false. + */ + bool IsRemoteData(); + + /** + * GetDataSource + * @descrition Obtain the package name of the data source application. + * @param std::string bundleName The package name of the application. + * @return int32_t. + */ + int32_t GetDataSource(std::string &bundleName); + + /** + * HasDataType + * @descrition Check if there is data of the specified type in the pasteboard. + * @param std::string mimeType Specified mimetype. + * @return bool. True exists, false does not exist + */ + bool HasDataType(const std::string &mimeType); + + /** + * AddPasteboardChangedObserver + * @descrition + * @param observer pasteboard change callback. + * @return void. + */ + void AddPasteboardChangedObserver(sptr callback); + + /** + * AddPasteboardEventObserver + * @descrition + * @param observer pasteboard event(read or change) callback. + * @return void. + */ + void AddPasteboardEventObserver(sptr callback); + + /** + * RemovePasteboardChangedObserver + * @descrition + * @param observer pasteboard change callback. + * @return void. + */ + void RemovePasteboardChangedObserver(sptr callback); + + /** + * RemovePasteboardEventObserver + * @descrition + * @param observer pasteboard event callback. + * @return void. + */ + void RemovePasteboardEventObserver(sptr callback); + + /** + * OnRemoteSaDied + * @descrition + * @param object systemAbility proxy object + * @return void. + */ + void OnRemoteSaDied(const wptr &object); + + /** + * LoadSystemAbilitySuccess + * @descrition inherit SystemAbilityLoadCallbackStub override LoadSystemAbilitySuccess + * @param remoteObject systemAbility proxy object. + * @return void. + */ + void LoadSystemAbilitySuccess(const sptr &remoteObject); + + /** + * LoadSystemAbilityFail + * @descrition inherit SystemAbilityLoadCallbackStub override LoadSystemAbilityFail + * @return void. + */ + void LoadSystemAbilityFail(); + +private: + inline bool IsServiceAvailable(); + void ConnectService(); + static void RetainUri(PasteData &pasteData); + static std::shared_ptr SplitWebviewPasteData(PasteData &pasteData); + static sptr pasteboardServiceProxy_; + static std::mutex instanceLock_; + static std::condition_variable proxyConVar_; + sptr deathRecipient_{ nullptr }; + class StaticDestoryMonitor { + public: + StaticDestoryMonitor() : destoryed_(false) {} + ~StaticDestoryMonitor() + { + destoryed_ = true; + } + + bool IsDestoryed() const + { + return destoryed_; + } + + private: + bool destoryed_; + }; + static StaticDestoryMonitor staticDestoryMonitor_; + void RebuildWebviewPasteData(PasteData &pasteData); +}; +} // namespace MiscServices +} // namespace OHOS +#endif // PASTE_BOARD_CLIENT_H diff --git a/pasteboard/framework/innerkits/include/pasteboard_load_callback.h b/pasteboard/framework/innerkits/include/pasteboard_load_callback.h new file mode 100644 index 00000000..4c7c0c1a --- /dev/null +++ b/pasteboard/framework/innerkits/include/pasteboard_load_callback.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_PASTE_BOARD_LOAD_CALLBACK_H +#define OHOS_PASTE_BOARD_LOAD_CALLBACK_H + +#include +#include + +#include "refbase.h" +#include "system_ability_load_callback_stub.h" + +namespace OHOS { +namespace MiscServices { +class PasteboardLoadCallback : public SystemAbilityLoadCallbackStub { +public: + void OnLoadSystemAbilitySuccess(int32_t systemAbilityId, const sptr &remoteObject) override; + void OnLoadSystemAbilityFail(int32_t systemAbilityId) override; +}; +} // namespace MiscServices +} // namespace OHOS +#endif // OHOS_PASTE_BOARD_LOAD_CALLBACK_H \ No newline at end of file diff --git a/pasteboard/framework/innerkits/include/pasteboard_observer.h b/pasteboard/framework/innerkits/include/pasteboard_observer.h new file mode 100644 index 00000000..c2e63999 --- /dev/null +++ b/pasteboard/framework/innerkits/include/pasteboard_observer.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef PASTE_BOARD_OBSERVER_H +#define PASTE_BOARD_OBSERVER_H + +#include "pasteboard_observer_stub.h" + +namespace OHOS { +namespace MiscServices { +class PasteboardObserver : public PasteboardObserverStub { +public: + PasteboardObserver(); + ~PasteboardObserver(); + void OnPasteboardChanged() override; + void OnPasteboardEvent(std::string bundleName, int32_t status) override; +}; +} // namespace MiscServices +} // namespace OHOS +#endif // PASTE_BOARD_OBSERVER_H diff --git a/pasteboard/framework/innerkits/include/pasteboard_web_controller.h b/pasteboard/framework/innerkits/include/pasteboard_web_controller.h new file mode 100644 index 00000000..c08a0b99 --- /dev/null +++ b/pasteboard/framework/innerkits/include/pasteboard_web_controller.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2023-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef WEB_CLIPBORD_CONTROLLER_H +#define WEB_CLIPBORD_CONTROLLER_H + +#include +#include +#include +#include +#include + +#include "paste_data.h" +#include "paste_data_record.h" +#include "refbase.h" + +namespace OHOS { +namespace MiscServices { + +class PasteboardWebController : public RefBase { +public: + PasteboardWebController() {}; + ~PasteboardWebController() {}; + + static PasteboardWebController& GetInstance(); + + std::shared_ptr SplitHtml(std::shared_ptr html) noexcept; + std::shared_ptr RebuildHtml(std::shared_ptr pasteData) noexcept; + +private: + std::vector> SplitHtmlWithImgLabel( + const std::shared_ptr html) noexcept; + std::map> SplitHtmlWithImgSrcLabel( + const std::vector>& matchVec) noexcept; + std::shared_ptr BuildPasteData( + std::shared_ptr html, const std::map>& imgSrcMap) noexcept; + void RemoveAllRecord(std::shared_ptr pasteData) noexcept; + bool IsLocalURI(std::string& uri) noexcept; +}; +} // namespace MiscServices +} // namespace OHOS + +#endif // WEB_CLIPBORD_CONTROLLER_H diff --git a/pasteboard/framework/innerkits/src/paste_data.cpp b/pasteboard/framework/innerkits/src/paste_data.cpp new file mode 100644 index 00000000..2a73ecc8 --- /dev/null +++ b/pasteboard/framework/innerkits/src/paste_data.cpp @@ -0,0 +1,658 @@ + +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "paste_data.h" + +#include + +#include "parcel_util.h" +#include "paste_data_record.h" +#include "pasteboard_hilog.h" +#include "type_traits" + +using namespace std::chrono; +using namespace OHOS::Media; + +namespace OHOS { +namespace MiscServices { +enum TAG_PASTEBOARD : uint16_t { TAG_PROPS = TAG_BUFF + 1, TAG_RECORDS, TAG_DRAGGED_DATA_FLAG, TAG_LOCAL_PASTE_FLAG }; +enum TAG_PROPERTY : uint16_t { + TAG_ADDITIONS = TAG_BUFF + 1, + TAG_MIMETYPES, + TAG_TAG, + TAG_LOCAL_ONLY, + TAG_TIMESTAMP, + TAG_SHAREOPTION, + TAG_TOKENID, + TAG_ISREMOTE, + TAG_BUNDLENAME, + TAG_SETTIME, +}; + +std::string PasteData::sharePath = ""; +std::string PasteData::WEBVIEW_PASTEDATA_TAG = "WebviewPasteDataTag"; +const std::string PasteData::DISTRIBUTEDFILES_TAG = "distributedfiles"; +const std::string PasteData::PATH_SHARE = "/data/storage/el2/share/r/"; +const std::string PasteData::FILE_SCHEME_PREFIX = "file://"; +const std::string PasteData::IMG_LOCAL_URI = "file:///"; +const std::string PasteData::SHARE_PATH_PREFIX = "/mnt/hmdfs/"; +const std::string PasteData::SHARE_PATH_PREFIX_ACCOUNT = "/account/merge_view/services/"; +const std::string PasteData::REMOTE_FILE_SIZE = "remoteFileSize"; + +PasteData::PasteData() +{ + props_.timestamp = steady_clock::now().time_since_epoch().count(); + props_.localOnly = false; + props_.shareOption = ShareOption::CrossDevice; +} + +PasteData::~PasteData() +{ + records_.clear(); +} + +PasteData::PasteData(const PasteData &data) : orginAuthority_(data.orginAuthority_), valid_(data.valid_), + isDraggedData_(data.isDraggedData_), isLocalPaste_(data.isLocalPaste_) +{ + this->props_ = data.props_; + for (const auto &item : data.records_) { + this->records_.emplace_back(std::make_shared(*item)); + } +} + +PasteData::PasteData(std::vector> records) : records_{ std::move(records) } +{ + props_.timestamp = steady_clock::now().time_since_epoch().count(); + props_.localOnly = false; + props_.shareOption = ShareOption::CrossDevice; +} + +PasteData& PasteData::operator=(const PasteData &data) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "PasteData copy"); + if (this == &data) { + return *this; + } + this->orginAuthority_ = data.orginAuthority_; + this->valid_ = data.valid_; + this->isDraggedData_ = data.isDraggedData_; + this->isLocalPaste_ = data.isLocalPaste_; + this->props_ = data.props_; + this->records_.clear(); + for (const auto &item : data.records_) { + this->records_.emplace_back(std::make_shared(*item)); + } + return *this; +} + + +PasteDataProperty PasteData::GetProperty() const +{ + return PasteDataProperty(props_); +} + +void PasteData::SetProperty(const PasteDataProperty &property) +{ + this->props_ = property; +} + +void PasteData::AddHtmlRecord(const std::string &html) +{ + this->AddRecord(PasteDataRecord::NewHtmlRecord(html)); +} + +void PasteData::AddPixelMapRecord(std::shared_ptr pixelMap) +{ + this->AddRecord(PasteDataRecord::NewPixelMapRecord(std::move(pixelMap))); +} + +void PasteData::AddWantRecord(std::shared_ptr want) +{ + this->AddRecord(PasteDataRecord::NewWantRecord(std::move(want))); +} + +void PasteData::AddTextRecord(const std::string &text) +{ + this->AddRecord(PasteDataRecord::NewPlaintTextRecord(text)); +} + +void PasteData::AddUriRecord(const OHOS::Uri &uri) +{ + this->AddRecord(PasteDataRecord::NewUriRecord(uri)); +} + +void PasteData::AddKvRecord(const std::string &mimeType, const std::vector &arrayBuffer) +{ + AddRecord(PasteDataRecord::NewKvRecord(mimeType, arrayBuffer)); +} + +void PasteData::AddRecord(std::shared_ptr record) +{ + if (record == nullptr) { + return; + } + records_.insert(records_.begin(), std::move(record)); + RefreshMimeProp(); +} + +void PasteData::AddRecord(PasteDataRecord &record) +{ + this->AddRecord(std::make_shared(record)); + RefreshMimeProp(); +} + +std::vector PasteData::GetMimeTypes() +{ + std::vector mimeType; + for (const auto &item : records_) { + mimeType.push_back(item->GetMimeType()); + } + return mimeType; +} + +std::shared_ptr PasteData::GetPrimaryHtml() +{ + for (const auto &item : records_) { + if (item->GetHtmlText() != nullptr) { + return item->GetHtmlText(); + } + } + return nullptr; +} + +std::shared_ptr PasteData::GetPrimaryPixelMap() +{ + for (const auto &item : records_) { + if (item->GetPixelMap() != nullptr) { + return item->GetPixelMap(); + } + } + return nullptr; +} + +std::shared_ptr PasteData::GetPrimaryWant() +{ + for (const auto &item : records_) { + if (item->GetWant() != nullptr) { + return item->GetWant(); + } + } + return nullptr; +} + +std::shared_ptr PasteData::GetPrimaryText() +{ + for (const auto &item : records_) { + if (item->GetPlainText() != nullptr) { + return item->GetPlainText(); + } + } + return nullptr; +} + +std::shared_ptr PasteData::GetPrimaryUri() +{ + for (const auto &item : records_) { + if (item->GetUri() != nullptr) { + return item->GetUri(); + } + } + return nullptr; +} + +std::shared_ptr PasteData::GetPrimaryMimeType() +{ + if (!records_.empty()) { + return std::make_shared(records_.front()->GetMimeType()); + } else { + return nullptr; + } +} + +std::shared_ptr PasteData::GetRecordAt(std::size_t index) +{ + if (records_.size() > index) { + return records_[index]; + } else { + return nullptr; + } +} + +std::size_t PasteData::GetRecordCount() +{ + return records_.size(); +} + +ShareOption PasteData::GetShareOption() +{ + return props_.shareOption; +} + +void PasteData::SetShareOption(ShareOption shareOption) +{ + props_.shareOption = shareOption; + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_CLIENT, "shareOption = %{public}d.", shareOption); +} + +std::uint32_t PasteData::GetTokenId() +{ + return props_.tokenId; +} + +void PasteData::SetTokenId(uint32_t tokenId) +{ + props_.tokenId = tokenId; +} + +bool PasteData::RemoveRecordAt(std::size_t number) +{ + if (records_.size() > number) { + records_.erase(records_.begin() + static_cast(number)); + RefreshMimeProp(); + return true; + } else { + return false; + } +} + +bool PasteData::ReplaceRecordAt(std::size_t number, std::shared_ptr record) +{ + if (records_.size() > number) { + records_[number] = std::move(record); + RefreshMimeProp(); + return true; + } else { + return false; + } +} + +bool PasteData::HasMimeType(const std::string &mimeType) +{ + for (auto &item : records_) { + if (item->GetMimeType() == mimeType) { + return true; + } + } + return false; +} + +std::vector> PasteData::AllRecords() const +{ + return this->records_; +} + +bool PasteData::IsDraggedData() const +{ + return isDraggedData_; +} + +bool PasteData::IsLocalPaste() const +{ + return isLocalPaste_; +} + +void PasteData::SetDraggedDataFlag(bool isDraggedData) +{ + isDraggedData_ = isDraggedData; +} + +void PasteData::SetLocalPasteFlag(bool isLocalPaste) +{ + isLocalPaste_ = isLocalPaste; +} + +void PasteData::SetRemote(bool isRemote) +{ + props_.isRemote = isRemote; +} + +bool PasteData::IsRemote() +{ + return props_.isRemote; +} + +void PasteData::SetBundleName(const std::string &bundleName) +{ + props_.bundleName = bundleName; +} + +std::string PasteData::GetBundleName() const +{ + return props_.bundleName; +} + +void PasteData::SetOrginAuthority(const std::string &bundleName) +{ + orginAuthority_ = bundleName; +} + +std::string PasteData::GetOrginAuthority() const +{ + return orginAuthority_; +} + +void PasteData::SetTime(const std::string &setTime) +{ + props_.setTime = setTime; +} + +std::string PasteData::GetTime() +{ + return props_.setTime; +} + +void PasteData::SetTag(std::string &tag) +{ + props_.tag = tag; +} + +std::string PasteData::GetTag() +{ + return props_.tag; +} + +void PasteData::SetAdditions(AAFwk::WantParams &additions) +{ + props_.additions = additions; +} + +void PasteData::SetAddition(const std::string &key, AAFwk::IInterface *value) +{ + props_.additions.SetParam(key, value); +} + +void PasteData::SetLocalOnly(bool localOnly) +{ + props_.localOnly = localOnly; +} + +bool PasteData::GetLocalOnly() +{ + return props_.localOnly; +} + +void PasteData::RefreshMimeProp() +{ + std::vector mimeTypes; + for (const auto &record : records_) { + if (record == nullptr) { + continue; + } + mimeTypes.insert(mimeTypes.end(), record->GetMimeType()); + } + props_.mimeTypes = mimeTypes; +} + +bool PasteData::Encode(std::vector &buffer) +{ + Init(buffer); + + bool ret = Write(buffer, TAG_PROPS, props_); + ret = Write(buffer, TAG_RECORDS, records_) && ret; + ret = Write(buffer, TAG_DRAGGED_DATA_FLAG, isDraggedData_) && ret; + ret = Write(buffer, TAG_LOCAL_PASTE_FLAG, isLocalPaste_) && ret; + return ret; +} + +bool PasteData::Decode(const std::vector &buffer) +{ + total_ = buffer.size(); + for (; IsEnough();) { + TLVHead head{}; + bool ret = ReadHead(buffer, head); + switch (head.tag) { + case TAG_PROPS: + ret = ret && ReadValue(buffer, props_, head); + break; + case TAG_RECORDS: { + ret = ret && ReadValue(buffer, records_, head); + break; + } + case TAG_DRAGGED_DATA_FLAG: { + ret = ret && ReadValue(buffer, isDraggedData_, head); + break; + } + case TAG_LOCAL_PASTE_FLAG: { + ret = ret && ReadValue(buffer, isLocalPaste_, head); + break; + } + default: + ret = ret && Skip(head.len, buffer.size()); + break; + } + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "read value,tag:%{public}u, len:%{public}u, ret:%{public}d", + head.tag, head.len, ret); + if (!ret) { + return false; + } + } + return true; +} +size_t PasteData::Count() +{ + size_t expectSize = 0; + expectSize += props_.Count() + sizeof(TLVHead); + expectSize += TLVObject::Count(records_); + expectSize += TLVObject::Count(isDraggedData_); + expectSize += TLVObject::Count(isLocalPaste_); + return expectSize; +} + +bool PasteData::IsValid() const +{ + return valid_; +} + +void PasteData::SetInvalid() +{ + valid_ = false; +} + +PasteDataProperty::PasteDataProperty(const PasteDataProperty &property) + : tag(property.tag), timestamp(property.timestamp), localOnly(property.localOnly), + shareOption(property.shareOption), tokenId(property.tokenId), isRemote(property.isRemote), + bundleName(property.bundleName), setTime(property.setTime) +{ + this->additions = property.additions; + std::copy(property.mimeTypes.begin(), property.mimeTypes.end(), std::back_inserter(this->mimeTypes)); +} + +PasteDataProperty::~PasteDataProperty() +{ + mimeTypes.clear(); +} + +PasteDataProperty& PasteDataProperty::operator=(const PasteDataProperty &property) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "PasteDataProperty copy"); + if (this == &property) { + return *this; + } + this->tag = property.tag; + this->timestamp = property.timestamp; + this->localOnly = property.localOnly; + this->shareOption = property.shareOption; + this->tokenId = property.tokenId; + this->isRemote = property.isRemote; + this->bundleName = property.bundleName; + this->setTime = property.setTime; + this->additions = property.additions; + this->mimeTypes.clear(); + std::copy(property.mimeTypes.begin(), property.mimeTypes.end(), std::back_inserter(this->mimeTypes)); + return *this; +} + + +bool PasteDataProperty::Encode(std::vector &buffer) +{ + bool ret = Write(buffer, TAG_ADDITIONS, ParcelUtil::Parcelable2Raw(&additions)); + ret = Write(buffer, TAG_MIMETYPES, mimeTypes) && ret; + ret = Write(buffer, TAG_TAG, tag) && ret; + ret = Write(buffer, TAG_LOCAL_ONLY, localOnly) && ret; + ret = Write(buffer, TAG_TIMESTAMP, timestamp) && ret; + ret = Write(buffer, TAG_SHAREOPTION, (int32_t &)shareOption) && ret; + ret = Write(buffer, TAG_TOKENID, tokenId) && ret; + ret = Write(buffer, TAG_ISREMOTE, isRemote) && ret; + ret = Write(buffer, TAG_BUNDLENAME, bundleName) && ret; + ret = Write(buffer, TAG_SETTIME, setTime) && ret; + return ret; +} + +bool PasteDataProperty::Decode(const std::vector &buffer) +{ + for (; IsEnough();) { + if (!DecodeTag(buffer)) { + return false; + } + } + return true; +} + +bool PasteDataProperty::DecodeTag(const std::vector &buffer) +{ + TLVHead head{}; + bool ret = ReadHead(buffer, head); + switch (head.tag) { + case TAG_ADDITIONS: { + RawMem rawMem{}; + ret = ret && ReadValue(buffer, rawMem, head); + auto buff = ParcelUtil::Raw2Parcelable(rawMem); + if (buff != nullptr) { + additions = *buff; + } + break; + } + case TAG_MIMETYPES: + ret = ret && ReadValue(buffer, mimeTypes, head); + break; + case TAG_TAG: + ret = ret && ReadValue(buffer, tag, head); + break; + case TAG_LOCAL_ONLY: + ret = ret && ReadValue(buffer, localOnly, head); + break; + case TAG_TIMESTAMP: + ret = ret && ReadValue(buffer, timestamp, head); + break; + case TAG_SHAREOPTION: + ret = ret && ReadValue(buffer, (int32_t &)shareOption, head); + break; + case TAG_TOKENID: + ret = ret && ReadValue(buffer, tokenId, head); + break; + case TAG_ISREMOTE: + ret = ret && ReadValue(buffer, isRemote, head); + break; + case TAG_BUNDLENAME: + ret = ret && ReadValue(buffer, bundleName, head); + break; + case TAG_SETTIME: + ret = ret && ReadValue(buffer, setTime, head); + break; + default: + ret = ret && Skip(head.len, buffer.size()); + break; + } + return ret; +} + +size_t PasteDataProperty::Count() +{ + size_t expectedSize = 0; + expectedSize += TLVObject::Count(ParcelUtil::Parcelable2Raw(&additions)); + expectedSize += TLVObject::Count(mimeTypes); + expectedSize += TLVObject::Count(tag); + expectedSize += TLVObject::Count(localOnly); + expectedSize += TLVObject::Count(timestamp); + expectedSize += TLVObject::Count(shareOption); + expectedSize += TLVObject::Count(tokenId); + expectedSize += TLVObject::Count(isRemote); + expectedSize += TLVObject::Count(bundleName); + expectedSize += TLVObject::Count(setTime); + return expectedSize; +} + +bool PasteData::WriteUriFd(MessageParcel &parcel, UriHandler &uriHandler, bool isClient) +{ + std::vector uriIndexList; + for (size_t i = 0; i < GetRecordCount(); ++i) { + auto record = GetRecordAt(i); + if (record == nullptr) { + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "record null"); + continue; + } + if (isLocalPaste_) { + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "isLocalPaste"); + continue; + } + if (record->NeedFd(uriHandler)) { + uriIndexList.push_back(i); + } + } + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "write fd vector size:%{public}zu", uriIndexList.size()); + if (!parcel.WriteUInt32Vector(uriIndexList)) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "Failed to write fd index vector"); + return false; + } + for (auto index : uriIndexList) { + auto record = GetRecordAt(index); + if (record == nullptr || !record->WriteFd(parcel, uriHandler, isClient)) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "Failed to write fd"); + return false; + } + } + return true; +} +bool PasteData::ReadUriFd(MessageParcel &parcel, UriHandler &uriHandler) +{ + std::vector fdRecordMap; + if (!parcel.ReadUInt32Vector(&fdRecordMap)) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "Failed to read fd index vector"); + return false; + } + for (auto index : fdRecordMap) { + auto record = GetRecordAt(index); + if (record == nullptr || !record->ReadFd(parcel, uriHandler)) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "Failed to read fd"); + return false; + } + } + return true; +} +void PasteData::ReplaceShareUri(int32_t userId) +{ + auto count = GetRecordCount(); + for (size_t i = 0; i < count; ++i) { + auto record = GetRecordAt(i); + if (record == nullptr) { + continue; + } + record->ReplaceShareUri(userId); + } +} + +void PasteData::ShareOptionToString(ShareOption shareOption, std::string &out) +{ + if (shareOption == ShareOption::InApp) { + out = "InAPP"; + } else if (shareOption == ShareOption::LocalDevice) { + out = "LocalDevice"; + } else { + out = "CrossDevice"; + } +} +} // namespace MiscServices +} // namespace OHOS \ No newline at end of file diff --git a/pasteboard/framework/innerkits/src/paste_data_record.cpp b/pasteboard/framework/innerkits/src/paste_data_record.cpp new file mode 100644 index 00000000..463a74ff --- /dev/null +++ b/pasteboard/framework/innerkits/src/paste_data_record.cpp @@ -0,0 +1,505 @@ +/* + * Copyright (C) 2021-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "paste_data_record.h" + +#include +#include + +#include "copy_uri_handler.h" +#include "parcel_util.h" +#include "paste_uri_handler.h" +#include "pasteboard_error.h" +#include "pasteboard_hilog.h" +#include "pixel_map_parcel.h" + +using namespace OHOS::Media; + +namespace OHOS { +namespace MiscServices { +namespace { +constexpr int MAX_TEXT_LEN = 20 * 1024 * 1024; +} + +PasteDataRecord::Builder &PasteDataRecord::Builder::SetMimeType(std::string mimeType) +{ + record_->mimeType_ = std::move(mimeType); + return *this; +} +enum TAG_PASTEBOARD_RECORD : uint16_t { + TAG_MIMETYPE = TAG_BUFF + 1, + TAG_HTMLTEXT, + TAG_WANT, + TAG_PLAINTEXT, + TAG_URI, + TAG_PIXELMAP, + TAG_CUSTOM_DATA, + TAG_CONVERT_URI, + TAG_URI_PERMISSION, +}; + +enum TAG_CUSTOMDATA : uint16_t { + TAG_ITEM_DATA = TAG_BUFF + 1, +}; + +PasteDataRecord::Builder &PasteDataRecord::Builder::SetHtmlText(std::shared_ptr htmlText) +{ + record_->htmlText_ = std::move(htmlText); + return *this; +} +PasteDataRecord::Builder &PasteDataRecord::Builder::SetWant(std::shared_ptr want) +{ + record_->want_ = std::move(want); + return *this; +} +PasteDataRecord::Builder &PasteDataRecord::Builder::SetPlainText(std::shared_ptr plainText) +{ + record_->plainText_ = std::move(plainText); + return *this; +} +PasteDataRecord::Builder &PasteDataRecord::Builder::SetUri(std::shared_ptr uri) +{ + record_->uri_ = std::move(uri); + return *this; +} +PasteDataRecord::Builder &PasteDataRecord::Builder::SetPixelMap(std::shared_ptr pixelMap) +{ + record_->pixelMap_ = std::move(pixelMap); + return *this; +} + +PasteDataRecord::Builder &PasteDataRecord::Builder::SetCustomData(std::shared_ptr customData) +{ + record_->customData_ = std::move(customData); + return *this; +} + +std::shared_ptr PasteDataRecord::Builder::Build() +{ + return record_; +} +PasteDataRecord::Builder::Builder(const std::string &mimeType) +{ + record_ = std::make_shared(); + if (record_ != nullptr) { + record_->mimeType_ = mimeType; + record_->htmlText_ = nullptr; + record_->want_ = nullptr; + record_->plainText_ = nullptr; + record_->uri_ = nullptr; + record_->convertUri_ = ""; + record_->pixelMap_ = nullptr; + record_->customData_ = nullptr; + } +} + +std::shared_ptr PasteDataRecord::NewHtmlRecord(const std::string &htmlText) +{ + if (htmlText.length() >= MAX_TEXT_LEN) { + return nullptr; + } + return Builder(MIMETYPE_TEXT_HTML).SetHtmlText(std::make_shared(htmlText)).Build(); +} + +std::shared_ptr PasteDataRecord::NewWantRecord(std::shared_ptr want) +{ + return Builder(MIMETYPE_TEXT_WANT).SetWant(std::move(want)).Build(); +} + +std::shared_ptr PasteDataRecord::NewPlaintTextRecord(const std::string &text) +{ + if (text.length() >= MAX_TEXT_LEN) { + return nullptr; + } + return Builder(MIMETYPE_TEXT_PLAIN).SetPlainText(std::make_shared(text)).Build(); +} + +std::shared_ptr PasteDataRecord::NewPixelMapRecord(std::shared_ptr pixelMap) +{ + return Builder(MIMETYPE_PIXELMAP).SetPixelMap(std::move(pixelMap)).Build(); +} + +std::shared_ptr PasteDataRecord::NewUriRecord(const OHOS::Uri &uri) +{ + return Builder(MIMETYPE_TEXT_URI).SetUri(std::make_shared(uri)).Build(); +} + +std::shared_ptr PasteDataRecord::NewKvRecord( + const std::string &mimeType, const std::vector &arrayBuffer) +{ + std::shared_ptr customData = std::make_shared(); + customData->AddItemData(mimeType, arrayBuffer); + return Builder(mimeType).SetCustomData(std::move(customData)).Build(); +} + +PasteDataRecord::PasteDataRecord(std::string mimeType, std::shared_ptr htmlText, + std::shared_ptr want, std::shared_ptr plainText, std::shared_ptr uri) + : mimeType_{ std::move(mimeType) }, htmlText_{ std::move(htmlText) }, want_{ std::move(want) }, + plainText_{ std::move(plainText) }, uri_{ std::move(uri) } +{ +} + +PasteDataRecord::PasteDataRecord() +{ + fd_ = std::make_shared(); + InitDecodeMap(); +} + +PasteDataRecord::~PasteDataRecord() +{ + decodeMap.clear(); +} + +PasteDataRecord::PasteDataRecord(const PasteDataRecord &record) : mimeType_(record.mimeType_), + htmlText_(record.htmlText_), want_(record.want_), plainText_(record.plainText_), uri_(record.uri_), + convertUri_(record.convertUri_), pixelMap_(record.pixelMap_), customData_(record.customData_), + hasGrantUriPermission_(record.hasGrantUriPermission_), fd_(record.fd_) +{ + this->isConvertUriFromRemote = record.isConvertUriFromRemote; + InitDecodeMap(); +} + +void PasteDataRecord::InitDecodeMap() +{ + decodeMap = { + {TAG_MIMETYPE, [&](bool &ret, const std::vector &buffer, TLVHead &head) -> void { + ret = ret && ReadValue(buffer, mimeType_, head); + } + }, + {TAG_HTMLTEXT, [&](bool &ret, const std::vector &buffer, TLVHead &head) -> void { + ret = ret && ReadValue(buffer, htmlText_, head); + } + }, + {TAG_WANT, [&](bool &ret, const std::vector &buffer, TLVHead &head) -> void { + RawMem rawMem{}; + ret = ret && ReadValue(buffer, rawMem, head); + want_ = ParcelUtil::Raw2Parcelable(rawMem); + } + }, + {TAG_PLAINTEXT, [&](bool &ret, const std::vector &buffer, TLVHead &head) -> void { + ret = ret && ReadValue(buffer, plainText_, head); + } + }, + {TAG_URI, [&](bool &ret, const std::vector &buffer, TLVHead &head) -> void { + RawMem rawMem{}; + ret = ret && ReadValue(buffer, rawMem, head); + uri_ = ParcelUtil::Raw2Parcelable(rawMem); + } + }, + {TAG_CONVERT_URI, [&](bool &ret, const std::vector &buffer, TLVHead &head) -> void { + ret = ret && ReadValue(buffer, convertUri_, head); + } + }, + {TAG_PIXELMAP, [&](bool &ret, const std::vector &buffer, TLVHead &head) -> void { + std::vector value; + ret = ret && ReadValue(buffer, value, head); + pixelMap_ = Vector2PixelMap(value); + } + }, + {TAG_CUSTOM_DATA, [&](bool &ret, const std::vector &buffer, TLVHead &head) -> void { + ret = ret && ReadValue(buffer, customData_, head); + } + }, + {TAG_URI_PERMISSION, [&](bool &ret, const std::vector &buffer, TLVHead &head) -> void { + ret = ret && ReadValue(buffer, hasGrantUriPermission_, head); + } + }, + }; +} + +std::shared_ptr PasteDataRecord::GetHtmlText() const +{ + return this->htmlText_; +} + +std::string PasteDataRecord::GetMimeType() const +{ + return this->mimeType_; +} + +std::shared_ptr PasteDataRecord::GetPlainText() const +{ + return this->plainText_; +} + +std::shared_ptr PasteDataRecord::GetPixelMap() const +{ + return this->pixelMap_; +} + +std::shared_ptr PasteDataRecord::GetUri() const +{ + if (convertUri_.empty()) { + return uri_; + } + return std::make_shared(convertUri_); +} + +void PasteDataRecord::ClearPixelMap() +{ + this->pixelMap_ = nullptr; +} + +void PasteDataRecord::SetUri(std::shared_ptr uri) +{ + uri_ = std::move(uri); +} + +std::shared_ptr PasteDataRecord::GetOrginUri() const +{ + return uri_; +} + +std::shared_ptr PasteDataRecord::GetWant() const +{ + return this->want_; +} + +std::shared_ptr PasteDataRecord::GetCustomData() const +{ + return this->customData_; +} + +std::map> MineCustomData::GetItemData() +{ + return this->itemData_; +} + +void MineCustomData::AddItemData(const std::string &mimeType, const std::vector &arrayBuffer) +{ + itemData_.insert(std::make_pair(mimeType, arrayBuffer)); + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_CLIENT, "itemData_.size = %{public}zu", itemData_.size()); +} + +std::string PasteDataRecord::ConvertToText() const +{ + if (this->htmlText_) { + return *this->htmlText_; + } else if (this->plainText_) { + return *this->plainText_; + } else if (this->uri_) { + return this->uri_->ToString(); + } else { + return ""; + } +} + +bool MineCustomData::Encode(std::vector &buffer) +{ + return TLVObject::Write(buffer, TAG_ITEM_DATA, itemData_); +} + +bool MineCustomData::Decode(const std::vector &buffer) +{ + for (; IsEnough();) { + TLVHead head{}; + bool ret = ReadHead(buffer, head); + switch (head.tag) { + case TAG_ITEM_DATA: + ret = ret && ReadValue(buffer, itemData_, head); + break; + default: + ret = ret && Skip(head.len, buffer.size()); + break; + } + if (!ret) { + return false; + } + } + return true; +} + +size_t MineCustomData::Count() +{ + return TLVObject::Count(itemData_); +} + +bool PasteDataRecord::Encode(std::vector &buffer) +{ + bool ret = Write(buffer, TAG_MIMETYPE, mimeType_); + ret = Write(buffer, TAG_HTMLTEXT, htmlText_) && ret; + ret = Write(buffer, TAG_WANT, ParcelUtil::Parcelable2Raw(want_.get())) && ret; + ret = Write(buffer, TAG_PLAINTEXT, plainText_) && ret; + ret = Write(buffer, TAG_URI, ParcelUtil::Parcelable2Raw(uri_.get())) && ret; + ret = Write(buffer, TAG_CONVERT_URI, convertUri_) && ret; + auto pixelVector = PixelMap2Vector(pixelMap_); + ret = Write(buffer, TAG_PIXELMAP, pixelVector) && ret; + ret = Write(buffer, TAG_CUSTOM_DATA, customData_) && ret; + ret = Write(buffer, TAG_URI_PERMISSION, hasGrantUriPermission_) && ret; + return ret; +} + +bool PasteDataRecord::Decode(const std::vector &buffer) +{ + for (; IsEnough();) { + TLVHead head{}; + bool ret = ReadHead(buffer, head); + auto it = decodeMap.find(head.tag); + if (it == decodeMap.end()) { + ret = ret && Skip(head.len, buffer.size()); + } else { + auto func = it->second; + func(ret, buffer, head); + } + if (!ret) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "read value,tag:%{public}u, len:%{public}u", + head.tag, head.len); + return false; + } + } + return true; +} +size_t PasteDataRecord::Count() +{ + size_t expectedSize = 0; + expectedSize += TLVObject::Count(mimeType_); + expectedSize += TLVObject::Count(htmlText_); + expectedSize += TLVObject::Count(ParcelUtil::Parcelable2Raw(want_.get())); + expectedSize += TLVObject::Count(plainText_); + expectedSize += TLVObject::Count(ParcelUtil::Parcelable2Raw(uri_.get())); + expectedSize += TLVObject::Count(convertUri_); + auto pixelVector = PixelMap2Vector(pixelMap_); + expectedSize += TLVObject::Count(pixelVector); + expectedSize += TLVObject::Count(customData_); + expectedSize += TLVObject::Count(hasGrantUriPermission_); + return expectedSize; +} + +std::shared_ptr PasteDataRecord::Vector2PixelMap(std::vector &value) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "Vector2PixelMap, size is %{public}zu", value.size()); + if (value.size() == 0) { + return nullptr; + } + return std::shared_ptr (PixelMap::DecodeTlv(value)); +} + +std::vector PasteDataRecord::PixelMap2Vector(std::shared_ptr &pixelMap) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "PixelMap2Vector"); + if (pixelMap == nullptr) { + return {}; + } + std::vector value; + if (!pixelMap->EncodeTlv(value)) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "pixelMap encode failed"); + return {}; + } + return value; +} + +bool PasteDataRecord::WriteFd(MessageParcel &parcel, UriHandler &uriHandler, bool isClient) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "isClient: %{public}d", isClient); + if (fd_->GetFd() >= 0) { + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "write fd_, fd_ is %{public}d", fd_->GetFd()); + return parcel.WriteFileDescriptor(fd_->GetFd()); + } + std::string tempUri = GetPassUri(); + if (tempUri.empty()) { + return false; + } + int32_t fd = uriHandler.ToFd(tempUri, isClient); + bool ret = parcel.WriteFileDescriptor(fd); + uriHandler.ReleaseFd(fd); + + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "ret is %{public}d", ret); + return ret; +} +bool PasteDataRecord::ReadFd(MessageParcel &parcel, UriHandler &uriHandler) +{ + int32_t fd = parcel.ReadFileDescriptor(); + if (fd >= 0) { + convertUri_ = uriHandler.ToUri(fd); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "convertUri_:%{public}s", convertUri_.c_str()); + } + if (!uriHandler.IsPaste()) { + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "Set fd, fd is %{public}d", fd); + fd_->SetFd(fd); + } + return true; +} +bool PasteDataRecord::NeedFd(const UriHandler &uriHandler) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "start"); + std::string tempUri = GetPassUri(); + if (tempUri.empty()) { + return false; + } + if (!uriHandler.IsFile(tempUri) && fd_->GetFd() < 0) { + PASTEBOARD_HILOGW(PASTEBOARD_MODULE_CLIENT, "invalid file uri, fd:%{public}d", fd_->GetFd()); + return false; + } + return true; +} +std::string PasteDataRecord::GetPassUri() +{ + std::string tempUri; + if (uri_ != nullptr) { + tempUri = uri_->ToString(); + } + if (!convertUri_.empty()) { + tempUri = convertUri_; + } + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "tempUri:%{public}s", tempUri.c_str()); + return tempUri; +} +void PasteDataRecord::ReplaceShareUri(int32_t userId) +{ + if (convertUri_.empty()) { + return; + } + + // convert uri format: /mnt/hmdfs/100/account/merge_view/services/psteboard_service/.share/xxx.txt + constexpr const char *SHARE_PATH_PREFIX = "/mnt/hmdfs/"; + auto frontPos = convertUri_.find(SHARE_PATH_PREFIX); + auto rearPos = convertUri_.find("/account/"); + if (frontPos == 0 && rearPos != std::string::npos) { + convertUri_ = SHARE_PATH_PREFIX + std::to_string(userId) + convertUri_.substr(rearPos); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "replace uri:%{public}s", convertUri_.c_str()); + } +} +void PasteDataRecord::SetConvertUri(const std::string &value) +{ + convertUri_ = value; +} +std::string PasteDataRecord::GetConvertUri() const +{ + return convertUri_; +} +void PasteDataRecord::SetGrantUriPermission(bool hasPermission) +{ + hasGrantUriPermission_ = hasPermission; +} +bool PasteDataRecord::HasGrantUriPermission() +{ + return hasGrantUriPermission_; +} +FileDescriptor::~FileDescriptor() +{ + if (fd_ >= 0) { + close(fd_); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "close fd_: %{public}d", fd_); + } +} +void FileDescriptor::SetFd(int32_t fd) +{ + fd_ = fd; +} +int32_t FileDescriptor::GetFd() const +{ + return fd_; +} +} // namespace MiscServices +} // namespace OHOS \ No newline at end of file diff --git a/pasteboard/framework/innerkits/src/pasteboard_client.cpp b/pasteboard/framework/innerkits/src/pasteboard_client.cpp new file mode 100644 index 00000000..4796d04f --- /dev/null +++ b/pasteboard/framework/innerkits/src/pasteboard_client.cpp @@ -0,0 +1,461 @@ +/* + * Copyright (c) 2021-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include "file_uri.h" +#include "hiview_adapter.h" +#include "hitrace_meter.h" +#include "pasteboard_client.h" +#include "pasteboard_error.h" +#include "pasteboard_load_callback.h" +#include "pasteboard_observer.h" +#include "string_ex.h" +#include "system_ability_definition.h" +#include "pasteboard_web_controller.h" + +using namespace OHOS::Media; + +namespace OHOS { +namespace MiscServices { +constexpr const int32_t HITRACE_GETPASTEDATA = 0; +constexpr int32_t LOADSA_TIMEOUT_MS = 10000; +sptr PasteboardClient::pasteboardServiceProxy_; +PasteboardClient::StaticDestoryMonitor PasteboardClient::staticDestoryMonitor_; +std::mutex PasteboardClient::instanceLock_; +std::condition_variable PasteboardClient::proxyConVar_; +PasteboardClient::PasteboardClient(){}; +PasteboardClient::~PasteboardClient() +{ + if (pasteboardServiceProxy_ != nullptr && !staticDestoryMonitor_.IsDestoryed()) { + auto remoteObject = pasteboardServiceProxy_->AsObject(); + if (remoteObject != nullptr) { + remoteObject->RemoveDeathRecipient(deathRecipient_); + } + } +} + +std::shared_ptr PasteboardClient::CreateHtmlTextRecord(const std::string &htmlText) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "New text record"); + return PasteDataRecord::NewHtmlRecord(htmlText); +} + +std::shared_ptr PasteboardClient::CreateWantRecord(std::shared_ptr want) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "New want record"); + return PasteDataRecord::NewWantRecord(std::move(want)); +} + +std::shared_ptr PasteboardClient::CreatePlainTextRecord(const std::string &text) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "New text record"); + return PasteDataRecord::NewPlaintTextRecord(text); +} + +std::shared_ptr PasteboardClient::CreatePixelMapRecord(std::shared_ptr pixelMap) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "New pixelMap record"); + return PasteDataRecord::NewPixelMapRecord(std::move(pixelMap)); +} + +std::shared_ptr PasteboardClient::CreateUriRecord(const OHOS::Uri &uri) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "New uri record"); + return PasteDataRecord::NewUriRecord(uri); +} + +std::shared_ptr PasteboardClient::CreateKvRecord( + const std::string &mimeType, const std::vector &arrayBuffer) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "New kv record"); + return PasteDataRecord::NewKvRecord(mimeType, arrayBuffer); +} + +std::shared_ptr PasteboardClient::CreateHtmlData(const std::string &htmlText) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "New htmlText data"); + auto pasteData = std::make_shared(); + pasteData->AddHtmlRecord(htmlText); + return pasteData; +} + +std::shared_ptr PasteboardClient::CreateWantData(std::shared_ptr want) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "New want data"); + auto pasteData = std::make_shared(); + pasteData->AddWantRecord(std::move(want)); + return pasteData; +} + +std::shared_ptr PasteboardClient::CreatePlainTextData(const std::string &text) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "New plain data"); + auto pasteData = std::make_shared(); + pasteData->AddTextRecord(text); + return pasteData; +} + +std::shared_ptr PasteboardClient::CreatePixelMapData(std::shared_ptr pixelMap) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "New pixelMap data"); + auto pasteData = std::make_shared(); + pasteData->AddPixelMapRecord(std::move(pixelMap)); + return pasteData; +} + +std::shared_ptr PasteboardClient::CreateUriData(const OHOS::Uri &uri) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "New uri data"); + auto pasteData = std::make_shared(); + pasteData->AddUriRecord(uri); + return pasteData; +} + +std::shared_ptr PasteboardClient::CreateKvData( + const std::string &mimeType, const std::vector &arrayBuffer) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "New Kv data"); + auto pasteData = std::make_shared(); + pasteData->AddKvRecord(mimeType, arrayBuffer); + return pasteData; +} + +void PasteboardClient::Clear() +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "Clear start."); + if (!IsServiceAvailable()) { + return; + } + pasteboardServiceProxy_->Clear(); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "Clear end."); + return; +} + +int32_t PasteboardClient::GetPasteData(PasteData &pasteData) +{ + StartAsyncTrace(HITRACE_TAG_MISC, "PasteboardClient::GetPasteData", HITRACE_GETPASTEDATA); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "GetPasteData start."); + if (!IsServiceAvailable()) { + return static_cast(PasteboardError::E_SA_DIED); + } + int32_t ret = pasteboardServiceProxy_->GetPasteData(pasteData); + RetainUri(pasteData); + RebuildWebviewPasteData(pasteData); + FinishAsyncTrace(HITRACE_TAG_MISC, "PasteboardClient::GetPasteData", HITRACE_GETPASTEDATA); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "GetPasteData end."); + return ret; +} + +void PasteboardClient::RebuildWebviewPasteData(PasteData &pasteData) +{ + if (pasteData.GetTag() != PasteData::WEBVIEW_PASTEDATA_TAG || pasteData.GetPrimaryHtml() == nullptr) { + return; + } + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "Rebuild webview PasteData start."); + for (auto& item : pasteData.AllRecords()) { + if (item->GetUri() == nullptr) { + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "Rebuild webview one of uri is null."); + continue; + } + std::shared_ptr uri = item->GetUri(); + std::string puri = uri->ToString(); + std::string realUri = puri; + if (puri.substr(0, PasteData::FILE_SCHEME_PREFIX.size()) == PasteData::FILE_SCHEME_PREFIX) { + AppFileService::ModuleFileUri::FileUri fileUri(puri); + realUri = PasteData::FILE_SCHEME_PREFIX + fileUri.GetRealPath(); + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_CLIENT, "Rebuild webview uri is file uri."); + } + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "Rebuild webview realUri is = %{public}s.", realUri.c_str()); + if (realUri.find(PasteData::DISTRIBUTEDFILES_TAG) != std::string::npos) { + item->SetConvertUri(realUri); + } else { + item->SetUri(std::make_shared(realUri)); + } + } + auto PasteboardWebController = PasteboardWebController::GetInstance(); + auto webData = std::make_shared(pasteData); + PasteboardWebController.RebuildHtml(webData); + + std::shared_ptr primaryText = pasteData.GetPrimaryText(); + std::shared_ptr html = webData->GetPrimaryHtml(); + std::string mimeType = MIMETYPE_TEXT_HTML; + PasteDataRecord::Builder builder(MIMETYPE_TEXT_HTML); + std::shared_ptr pasteDataRecord = + builder.SetMimeType(mimeType).SetPlainText(primaryText).SetHtmlText(html).Build(); + webData->AddRecord(pasteDataRecord); + webData->RemoveRecordAt(webData->GetRecordCount() - 1); + pasteData = *webData; + + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "Rebuild webview PasteData end."); +} + +void PasteboardClient::RetainUri(PasteData &pasteData) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "RetainUri start."); + if (!pasteData.IsLocalPaste()) { + return; + } + // clear convert uri + for (size_t i = 0; i < pasteData.GetRecordCount(); ++i) { + auto record = pasteData.GetRecordAt(i); + if (record != nullptr) { + record->SetConvertUri(""); + } + } + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "RetainUri end."); +} + +bool PasteboardClient::HasPasteData() +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "HasPasteData start."); + if (!IsServiceAvailable()) { + return false; + } + return pasteboardServiceProxy_->HasPasteData(); +} + +int32_t PasteboardClient::SetPasteData(PasteData &pasteData) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "SetPasteData start."); + if (!IsServiceAvailable()) { + return static_cast(PasteboardError::E_SA_DIED); + } + std::shared_ptr html = pasteData.GetPrimaryHtml(); + if (pasteData.GetTag() != PasteData::WEBVIEW_PASTEDATA_TAG || html == nullptr) { + return pasteboardServiceProxy_->SetPasteData(pasteData); + } + auto webData = SplitWebviewPasteData(pasteData); + if (webData == nullptr) { + return static_cast(PasteboardError::E_INVALID_VALUE); + } + return pasteboardServiceProxy_->SetPasteData(*webData); +} + +std::shared_ptr PasteboardClient::SplitWebviewPasteData(PasteData &pasteData) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "SplitWebviewPasteData start."); + std::shared_ptr html = pasteData.GetPrimaryHtml(); + std::shared_ptr primaryText = pasteData.GetPrimaryText(); + auto PasteboardWebController = PasteboardWebController::GetInstance(); + std::shared_ptr webPasteData = PasteboardWebController.SplitHtml(html); + webPasteData->SetProperty(pasteData.GetProperty()); + std::string mimeType = MIMETYPE_TEXT_HTML; + PasteDataRecord::Builder builder(MIMETYPE_TEXT_HTML); + std::shared_ptr pasteDataRecord = + builder.SetMimeType(mimeType).SetPlainText(primaryText).SetHtmlText(html).Build(); + webPasteData->AddRecord(pasteDataRecord); + webPasteData->RemoveRecordAt(webPasteData->GetRecordCount() - 1); + webPasteData->SetTag(PasteData::WEBVIEW_PASTEDATA_TAG); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "SplitWebviewPasteData end."); + return webPasteData; +} + +void PasteboardClient::AddPasteboardChangedObserver(sptr callback) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "start."); + if (callback == nullptr) { + PASTEBOARD_HILOGW(PASTEBOARD_MODULE_CLIENT, "input nullptr."); + return; + } + if (!IsServiceAvailable()) { + return; + } + pasteboardServiceProxy_->AddPasteboardChangedObserver(callback); + return; +} + +void PasteboardClient::AddPasteboardEventObserver(sptr callback) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "start."); + if (callback == nullptr) { + PASTEBOARD_HILOGW(PASTEBOARD_MODULE_CLIENT, "input nullptr."); + return; + } + if (!IsServiceAvailable()) { + return; + } + pasteboardServiceProxy_->AddPasteboardEventObserver(callback); +} + +void PasteboardClient::RemovePasteboardChangedObserver(sptr callback) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "start."); + if (!IsServiceAvailable()) { + return; + } + if (callback == nullptr) { + PASTEBOARD_HILOGW(PASTEBOARD_MODULE_CLIENT, "remove all."); + pasteboardServiceProxy_->RemoveAllChangedObserver(); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "end."); + return; + } + pasteboardServiceProxy_->RemovePasteboardChangedObserver(callback); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "end."); + return; +} + +void PasteboardClient::RemovePasteboardEventObserver(sptr callback) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "start."); + if (!IsServiceAvailable()) { + return; + } + if (callback == nullptr) { + PASTEBOARD_HILOGW(PASTEBOARD_MODULE_CLIENT, "remove all."); + pasteboardServiceProxy_->RemoveAllEventObserver(); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "end."); + return; + } + pasteboardServiceProxy_->RemovePasteboardEventObserver(callback); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "end."); +} + +bool PasteboardClient::IsRemoteData() +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "IsRemoteData start."); + if (!IsServiceAvailable()) { + return false; + } + auto ret = pasteboardServiceProxy_->IsRemoteData(); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "IsRemoteData end."); + return ret; +} + +int32_t PasteboardClient::GetDataSource(std::string &bundleName) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "GetDataSource start."); + if (!IsServiceAvailable()) { + return static_cast(PasteboardError::E_SA_DIED); + } + int32_t ret = pasteboardServiceProxy_->GetDataSource(bundleName); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "GetDataSource end."); + return ret; +} + +bool PasteboardClient::HasDataType(const std::string &mimeType) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "HasDataType start."); + if (!IsServiceAvailable()) { + return false; + } + if (mimeType.empty()) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "parameter is invalid"); + return false; + } + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "type is %{public}s", mimeType.c_str()); + bool ret = pasteboardServiceProxy_->HasDataType(mimeType); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "HasDataType end."); + return ret; +} + +inline bool PasteboardClient::IsServiceAvailable() +{ + if (pasteboardServiceProxy_ == nullptr) { + PASTEBOARD_HILOGW(PASTEBOARD_MODULE_CLIENT, "Redo ConnectService"); + ConnectService(); + } + + if (pasteboardServiceProxy_ == nullptr) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "Service proxy null."); + return false; + } + return true; +} + +void PasteboardClient::ConnectService() +{ + std::unique_lock lock(instanceLock_); + if (pasteboardServiceProxy_ != nullptr) { + return; + } + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_CLIENT, "ConnectService start."); + sptr samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (samgrProxy == nullptr) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "Get SystemAbilityManager failed."); + pasteboardServiceProxy_ = nullptr; + return; + } + sptr remoteObject = samgrProxy->CheckSystemAbility(PASTEBOARD_SERVICE_ID); + if (remoteObject != nullptr) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "Get PasteboardServiceProxy succeed."); + if (deathRecipient_ == nullptr) { + deathRecipient_ = sptr(new PasteboardSaDeathRecipient()); + } + remoteObject->AddDeathRecipient(deathRecipient_); + pasteboardServiceProxy_ = iface_cast(remoteObject); + return; + } + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "remoteObject is null."); + sptr loadCallback = new PasteboardLoadCallback(); + if (loadCallback == nullptr) { + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_CLIENT, "loadCallback is nullptr."); + return; + } + int32_t ret = samgrProxy->LoadSystemAbility(PASTEBOARD_SERVICE_ID, loadCallback); + if (ret != ERR_OK) { + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_CLIENT, "Failed to load systemAbility."); + return; + } + auto waitStatus = proxyConVar_.wait_for(lock, std::chrono::milliseconds(LOADSA_TIMEOUT_MS), + [this]() { return pasteboardServiceProxy_ != nullptr; }); + if (!waitStatus) { + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_CLIENT, "Load systemAbility timeout."); + return; + } + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "Getting PasteboardServiceProxy succeeded."); +} + +void PasteboardClient::LoadSystemAbilitySuccess(const sptr &remoteObject) +{ + std::lock_guard lock(instanceLock_); + if (deathRecipient_ == nullptr) { + deathRecipient_ = sptr(new PasteboardSaDeathRecipient()); + } + if (remoteObject != nullptr) { + remoteObject->AddDeathRecipient(deathRecipient_); + pasteboardServiceProxy_ = iface_cast(remoteObject); + } + proxyConVar_.notify_one(); +} + +void PasteboardClient::LoadSystemAbilityFail() +{ + std::lock_guard lock(instanceLock_); + pasteboardServiceProxy_ = nullptr; + proxyConVar_.notify_one(); +} + +void PasteboardClient::OnRemoteSaDied(const wptr &remote) +{ + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_CLIENT, "OnRemoteSaDied start."); + pasteboardServiceProxy_ = nullptr; + ConnectService(); +} + +PasteboardSaDeathRecipient::PasteboardSaDeathRecipient() +{ +} + +void PasteboardSaDeathRecipient::OnRemoteDied(const wptr &object) +{ + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "PasteboardSaDeathRecipient on remote systemAbility died."); + PasteboardClient::GetInstance()->OnRemoteSaDied(object); +} +} // namespace MiscServices +} // namespace OHOS diff --git a/pasteboard/framework/innerkits/src/pasteboard_load_callback.cpp b/pasteboard/framework/innerkits/src/pasteboard_load_callback.cpp new file mode 100644 index 00000000..a812b150 --- /dev/null +++ b/pasteboard/framework/innerkits/src/pasteboard_load_callback.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "pasteboard_load_callback.h" +#include "pasteboard_client.h" + +namespace OHOS { +namespace MiscServices { + +void PasteboardLoadCallback::OnLoadSystemAbilitySuccess( + int32_t systemAbilityId, const sptr &remoteObject) +{ + PasteboardClient::GetInstance()->LoadSystemAbilitySuccess(remoteObject); + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_CLIENT, "Load system ability successed!"); +} + +void PasteboardLoadCallback::OnLoadSystemAbilityFail(int32_t systemAbilityId) +{ + PasteboardClient::GetInstance()->LoadSystemAbilityFail(); + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_CLIENT, "Load system ability failed!"); +} +} +} \ No newline at end of file diff --git a/pasteboard/framework/innerkits/src/pasteboard_observer.cpp b/pasteboard/framework/innerkits/src/pasteboard_observer.cpp new file mode 100644 index 00000000..f8f71e77 --- /dev/null +++ b/pasteboard/framework/innerkits/src/pasteboard_observer.cpp @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "pasteboard_observer.h" + +namespace OHOS { +namespace MiscServices { +PasteboardObserver::PasteboardObserver() +{ + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "New Pasteboard Observer."); +} + +PasteboardObserver::~PasteboardObserver() {} + +void PasteboardObserver::OnPasteboardChanged() +{ + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "changed callback."); +} + +void PasteboardObserver::OnPasteboardEvent(std::string bundleName, int32_t status) +{ + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "event callback."); +} +} // namespace MiscServices +} // namespace OHOS \ No newline at end of file diff --git a/pasteboard/framework/innerkits/src/pasteboard_web_controller.cpp b/pasteboard/framework/innerkits/src/pasteboard_web_controller.cpp new file mode 100644 index 00000000..a18aa667 --- /dev/null +++ b/pasteboard/framework/innerkits/src/pasteboard_web_controller.cpp @@ -0,0 +1,175 @@ +/* + * Copyright (C) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "file_uri.h" +#include "pasteboard_web_controller.h" + +namespace { +const std::string IMG_TAG_PATTERN = ""; +const std::string IMG_TAG_SRC_PATTERN = "src=(['\"])(.*?)\\1"; +const std::string IMG_TAG_SRC_HEAD = "src=\""; +const std::string IMG_LOCAL_URI = "file:///"; +const std::string IMG_LOCAL_PATH = "://"; +constexpr uint32_t FOUR_BYTES = 4; +constexpr uint32_t EIGHT_BIT = 8; + +struct Cmp { + bool operator()(const uint32_t& lhs, const uint32_t& rhs) const + { + return lhs > rhs; + } +}; +} // namespace + +namespace OHOS { +namespace MiscServices { + +// static +PasteboardWebController& PasteboardWebController::GetInstance() +{ + static PasteboardWebController instance; + return instance; +} + +std::shared_ptr PasteboardWebController::SplitHtml(std::shared_ptr html) noexcept +{ + std::vector> matchVec = SplitHtmlWithImgLabel(html); + std::map> imgSrcMap = SplitHtmlWithImgSrcLabel(matchVec); + std::shared_ptr pasteData = BuildPasteData(html, imgSrcMap); + return pasteData; +} + +std::shared_ptr PasteboardWebController::RebuildHtml( + std::shared_ptr pasteData) noexcept +{ + std::vector> pasteDataRecords = pasteData->AllRecords(); + std::shared_ptr htmlData; + std::map, Cmp> replaceUris; + + for (auto& item : pasteDataRecords) { + std::shared_ptr html = item->GetHtmlText(); + if (html) { + htmlData = html; + } + std::shared_ptr uri = item->GetUri(); + std::shared_ptr customData = item->GetCustomData(); + if (!uri || !customData) { + continue; + } + std::map> customItemData = customData->GetItemData(); + for (auto& itemData : customItemData) { + for (uint32_t i = 0; i < itemData.second.size(); i += FOUR_BYTES) { + uint32_t offset = static_cast(itemData.second[i]) | + static_cast(itemData.second[i + 1] << 8) | + static_cast(itemData.second[i + 2] << 16) | + static_cast(itemData.second[i + 3] << 24); + replaceUris[offset] = std::make_pair(uri->ToString(), itemData.first); + } + } + } + + RemoveAllRecord(pasteData); + for (auto& replaceUri : replaceUris) { + htmlData->replace(replaceUri.first, replaceUri.second.second.size(), replaceUri.second.first); + } + pasteData->AddHtmlRecord(*htmlData); + return htmlData; +} + +std::vector> PasteboardWebController::SplitHtmlWithImgLabel( + const std::shared_ptr html) noexcept +{ + std::smatch results; + std::string pattern(IMG_TAG_PATTERN); + std::regex r(pattern); + std::string::const_iterator iterStart = html->begin(); + std::string::const_iterator iterEnd = html->end(); + std::vector> matchVec; + + while (std::regex_search(iterStart, iterEnd, results, r)) { + std::string tmp = results[0]; + iterStart = results[0].second; + uint32_t offset = static_cast(results[0].first - html->begin()); + + matchVec.emplace_back(std::make_pair(tmp, offset)); + } + + return matchVec; +} + +std::map> PasteboardWebController::SplitHtmlWithImgSrcLabel( + const std::vector>& matchVec) noexcept +{ + std::map> res; + std::smatch match; + std::regex re(IMG_TAG_SRC_PATTERN); + for (auto& node : matchVec) { + std::string::const_iterator iterStart = node.first.begin(); + std::string::const_iterator iterEnd = node.first.end(); + + while (std::regex_search(iterStart, iterEnd, match, re)) { + std::string tmp = match[0]; + iterStart = match[0].second; + uint32_t offset = static_cast(match[0].first - node.first.begin()); + tmp = tmp.substr(IMG_TAG_SRC_HEAD.size()); + tmp.pop_back(); + if (!IsLocalURI(tmp)) { + continue; + } + offset += IMG_TAG_SRC_HEAD.size() + node.second; + for (uint32_t i = 0; i < FOUR_BYTES; i++) { + res[tmp].emplace_back((offset >> (EIGHT_BIT * i)) & 0xff); + } + } + } + return res; +} + +std::shared_ptr PasteboardWebController::BuildPasteData( + std::shared_ptr html, const std::map>& imgSrcMap) noexcept +{ + std::shared_ptr pasteData = std::make_shared(); + pasteData->AddHtmlRecord(*html); + for (auto& item : imgSrcMap) { + PasteDataRecord::Builder builder(MiscServices::MIMETYPE_TEXT_URI); + auto uri = std::make_shared(item.first); + builder.SetUri(uri); + auto customData = std::make_shared(); + + customData->AddItemData(item.first, item.second); + builder.SetCustomData(customData); + auto record = builder.Build(); + pasteData->AddRecord(record); + } + return pasteData; +} + +void PasteboardWebController::RemoveAllRecord(std::shared_ptr pasteData) noexcept +{ + std::size_t recordCount = pasteData->GetRecordCount(); + for (uint32_t i = 0; i < recordCount; i++) { + if (!pasteData->RemoveRecordAt(0)) { + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "WebClipboardController RemoveRecord failed, i=%{public}u", i); + } + } +} + +bool PasteboardWebController::IsLocalURI(std::string& uri) noexcept +{ + return uri.substr(0, IMG_LOCAL_URI.size()) == IMG_LOCAL_URI || uri.find(IMG_LOCAL_PATH) == std::string::npos; +} +} // namespace MiscServices +} // namespace OHOS diff --git a/pasteboard/framework/test/BUILD.gn b/pasteboard/framework/test/BUILD.gn new file mode 100644 index 00000000..1f68400d --- /dev/null +++ b/pasteboard/framework/test/BUILD.gn @@ -0,0 +1,88 @@ +# Copyright (c) 2022-2023 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") +import("//foundation/distributeddatamgr/pasteboard/pasteboard.gni") + +config("module_private_config") { + visibility = [ ":*" ] + + include_dirs = [ + "${pasteboard_innerkits_path}/include", + "//foundation/distributeddatamgr/pasteboard/framework/framework/include", + "//foundation/distributeddatamgr/pasteboard/framework/tlv", + "${pasteboard_root_path}/framework/framework/include/serializable", + "${pasteboard_service_path}/load/include", + "include", + "test/include", + ] +} + +module_output_path = "pasteboard/pasteboard_service" + +ohos_unittest("PasteboardFrameworkTest") { + resource_config_file = "//foundation/distributeddatamgr/pasteboard/framework/test/resource/ohos_test.xml" + module_out_path = module_output_path + + sources = [ + "${pasteboard_root_path}/framework/framework/serializable/serializable.cpp", + "${pasteboard_service_path}/load/src/config.cpp", + "src/clip_para_test.cpp", + "src/dm_adapter_test.cpp", + "src/paste_data_test.cpp", + "src/pasteboard_client_test.cpp", + "src/serializable_test.cpp", + "src/tlv_object_test.cpp", + "src/web_controller_test.cpp", + ] + configs = [ + "//commonlibrary/c_utils/base:utils_config", + ":module_private_config", + ] + external_deps = [ + "ability_base:base", + "ability_base:want", + "ability_base:zuri", + "app_file_service:remote_file_share_native", + "c_utils:utils", + "hilog:libhilog", + "image_framework:image_native", + "init:libbeget_proxy", + "init:libbegetutil", + "ipc:ipc_core", + ] + + deps = [ + "${pasteboard_framework_path}:pasteboard_framework", + "${pasteboard_innerkits_path}:pasteboard_client", + "//foundation/distributeddatamgr/pasteboard/framework/uri:pasteboard_uri", + "//third_party/googletest:gmock", + "//third_party/googletest:gtest_main", + ] + + defines = [] + + if (pb_device_info_manager_part_enabled) { + external_deps += [ "device_info_manager:distributed_device_profile_client" ] + defines += [ "PB_DEVICE_INFO_MANAGER_ENABLE" ] + } + + if (pb_device_manager_part_enabled) { + external_deps += [ "device_manager:devicemanagersdk" ] + defines += [ "PB_DEVICE_MANAGER_ENABLE" ] + } + + configs += [ "//third_party/cJSON:cJSON_config" ] + + deps += [ "//third_party/cJSON:cjson" ] +} diff --git a/pasteboard/framework/test/include/clip_factory.h b/pasteboard/framework/test/include/clip_factory.h new file mode 100644 index 00000000..b64fab8b --- /dev/null +++ b/pasteboard/framework/test/include/clip_factory.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2023-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PASTE_DATA_TEST_CLIP_FACTORY_H +#define PASTE_DATA_TEST_CLIP_FACTORY_H +#include "clip/clip_plugin.h" +namespace OHOS::MiscServices { +class ClipFactory : public ClipPlugin::Factory { +public: + ClipFactory(); + ~ClipFactory(); + ClipPlugin *Create() override; + bool Destroy(ClipPlugin *plugin) override; + +private: + ClipPlugin *clip_ = nullptr; + static ClipFactory factory_; +}; + +ClipPlugin *ClipFactory::Create() +{ + return clip_; +} + +bool ClipFactory::Destroy(ClipPlugin *plugin) +{ + if (plugin == clip_) { + delete clip_; + clip_ = nullptr; + return true; + } + return false; +} +} +#endif // PASTE_DATA_TEST_CLIP_FACTORY_H \ No newline at end of file diff --git a/pasteboard/framework/test/include/distributed_clip.h b/pasteboard/framework/test/include/distributed_clip.h new file mode 100644 index 00000000..76c82e11 --- /dev/null +++ b/pasteboard/framework/test/include/distributed_clip.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DISTRIBUTED_PASTEBOARD_FRAMEWORK_DISTRIBUTED_CLIP_H +#define DISTRIBUTED_PASTEBOARD_FRAMEWORK_DISTRIBUTED_CLIP_H +#include +#include +#include "device/dm_adapter.h" + +namespace OHOS::MiscServices { +class DistributedClip : public DMAdapter::DMObserver { +public: + void Online(const std::string &device) override; + void Offline(const std::string &device) override; + void OnReady(const std::string &device) override; +}; + +void DistributedClip::Online(const std::string &device) +{ +} + +void DistributedClip::Offline(const std::string &device) +{ +} + +void DistributedClip::OnReady(const std::string &device) +{ +} +} // namespace OHOS::MiscServices +#endif // DISTRIBUTED_PASTEBOARD_FRAMEWORK_DISTRIBUTED_CLIP_H diff --git a/pasteboard/framework/test/resource/ohos_test.xml b/pasteboard/framework/test/resource/ohos_test.xml new file mode 100644 index 00000000..366910a9 --- /dev/null +++ b/pasteboard/framework/test/resource/ohos_test.xml @@ -0,0 +1,22 @@ + + + + + + + + \ No newline at end of file diff --git a/pasteboard/framework/test/resource/pasteboardTest.txt b/pasteboard/framework/test/resource/pasteboardTest.txt new file mode 100644 index 00000000..5a57da94 --- /dev/null +++ b/pasteboard/framework/test/resource/pasteboardTest.txt @@ -0,0 +1,14 @@ +/* +* Copyright (C) 2022-2023 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ \ No newline at end of file diff --git a/pasteboard/framework/test/src/clip_para_test.cpp b/pasteboard/framework/test/src/clip_para_test.cpp new file mode 100644 index 00000000..44c9dd6d --- /dev/null +++ b/pasteboard/framework/test/src/clip_para_test.cpp @@ -0,0 +1,309 @@ +/* + * Copyright (c) 2023-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "device/clip_para.h" + +#include +#include + +namespace OHOS::MiscServices { +using namespace testing::ext; +using namespace std::chrono; +using namespace OHOS::MiscServices; +class ClipParaTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void ClipParaTest::SetUpTestCase(void) +{ +} + +void ClipParaTest::TearDownTestCase(void) +{ +} + +void ClipParaTest::SetUp(void) +{ +} + +void ClipParaTest::TearDown(void) +{ + ClipPara::GetInstance().InitMemberVariable(); +} + +/** +* @tc.name: InitMemberVariable_001 +* @tc.desc: Init Member Variable +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(ClipParaTest, InitMemberVariable_001, TestSize.Level0) +{ + ClipPara::GetInstance().InitMemberVariable(); + auto sendInformation = ClipPara::GetInstance().GetSendInformation(); + ASSERT_TRUE(sendInformation == nullptr); + auto remoteExpiration = ClipPara::GetInstance().GetRemoteExpiration(); + ASSERT_TRUE(remoteExpiration == 0); + std::string deviceId = "EDAFD0A26B93FB13F2FB8894EDB8DF9158B0E5CB63FAB4C94AEFD64A82D2F487"; + ClipPara::GetInstance().SetLastSyncNetworkId(deviceId); + auto lastSyncNetworkId = ClipPara::GetInstance().GetLastSyncNetworkId(); + ASSERT_TRUE(lastSyncNetworkId == deviceId); + auto isPullEvent = ClipPara::GetInstance().GetPullEvent(); + ASSERT_FALSE(isPullEvent); + auto isPullEventResult = ClipPara::GetInstance().GetPullEventResult(); + ASSERT_FALSE(isPullEventResult); + auto isPasted = ClipPara::GetInstance().GetPasted(); + ASSERT_FALSE(isPasted); +} + +/** +* @tc.name: LastLocalSyncKey_001 +* @tc.desc: test LastLocalSyncKey +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(ClipParaTest, LastLocalSyncKey_001, TestSize.Level0) +{ + ClipPara::GetInstance().InitMemberVariable(); + std::string lastLocalSyncKey = "event_100"; + ClipPara::GetInstance().SetLastLocalSyncKey(lastLocalSyncKey); + auto ret = ClipPara::GetInstance().GetLastLocalSyncKey(); + ASSERT_TRUE(ret == lastLocalSyncKey); +} + +/** +* @tc.name: LastRemoteSyncKey_001 +* @tc.desc: test LastRemoteSyncKey +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(ClipParaTest, LastRemoteSyncKey_001, TestSize.Level0) +{ + ClipPara::GetInstance().InitMemberVariable(); + std::string lastRemoteSyncKey = "event_100"; + ClipPara::GetInstance().SetLastRemoteSyncKey(lastRemoteSyncKey); + auto ret = ClipPara::GetInstance().GetLastRemoteSyncKey(); + ASSERT_TRUE(ret == lastRemoteSyncKey); +} + +/** +* @tc.name: LocalExpiration_001 +* @tc.desc: test LocalExpiration +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(ClipParaTest, LocalExpiration_001, TestSize.Level0) +{ + ClipPara::GetInstance().InitMemberVariable(); + uint64_t localExpiration = 10000; + ClipPara::GetInstance().SetLocalExpiration(localExpiration); + auto ret = ClipPara::GetInstance().GetLocalExpiration(); + ASSERT_TRUE(ret == localExpiration); +} + +/** +* @tc.name: RemoteExpiration_001 +* @tc.desc: test RemoteExpiration +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(ClipParaTest, RemoteExpiration_001, TestSize.Level0) +{ + ClipPara::GetInstance().InitMemberVariable(); + uint64_t remoteExpiration = 10000; + ClipPara::GetInstance().SetRemoteExpiration(remoteExpiration); + auto ret = ClipPara::GetInstance().GetRemoteExpiration(); + ASSERT_TRUE(ret == remoteExpiration); +} + +/** +* @tc.name: SendInformation_001 +* @tc.desc: Init Member Variable +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(ClipParaTest, SendInformation_001, TestSize.Level0) +{ + ClipPara::GetInstance().InitMemberVariable(); + ClipPara::SendInformation sendInformation; + ClipPara::GetInstance().SetSendInformation(sendInformation); + auto ret = ClipPara::GetInstance().GetSendInformation(); + ASSERT_TRUE(ret != nullptr); +} + +/** +* @tc.name: PullEventResult_001 +* @tc.desc: test PullEventResult +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(ClipParaTest, PullEventResult_001, TestSize.Level0) +{ + ClipPara::GetInstance().InitMemberVariable(); + ClipPara::GetInstance().SetPullEventResult(true); + auto ret = ClipPara::GetInstance().GetPullEventResult(); + ASSERT_TRUE(ret); +} + +/** +* @tc.name: HasRemoteData +* @tc.desc: Check Has Remote Data. +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(ClipParaTest, HasRemoteData_001, TestSize.Level0) +{ + ClipPara::GetInstance().InitMemberVariable(); + auto has = ClipPara::GetInstance().HasRemoteData(); + ASSERT_FALSE(has); +} + +/** +* @tc.name: GetActiveSync +* @tc.desc: test GetActiveSync. +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(ClipParaTest, GetActiveSync_001, TestSize.Level0) +{ + ClipPara::GetInstance().InitMemberVariable(); + bool activeSync; + activeSync = ClipPara::GetInstance().GetActiveSync(); + ASSERT_FALSE(activeSync); + ClipPara::GetInstance().SetActiveSync(true); + activeSync = ClipPara::GetInstance().GetActiveSync(); + ASSERT_TRUE(activeSync); +} + +/** +* @tc.name: GetFrameNum +* @tc.desc: test GetFrameNum. +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(ClipParaTest, GetFrameNum_001, TestSize.Level0) +{ + ClipPara::GetInstance().InitMemberVariable(); + uint8_t frameNum; + frameNum = ClipPara::GetInstance().GetFrameNum(); + ASSERT_TRUE(frameNum == 0); + ClipPara::GetInstance().SetFrameNum(10); + frameNum = ClipPara::GetInstance().GetFrameNum(); + ASSERT_TRUE(frameNum == 10); +} + +/** +* @tc.name: UpdateStageValue_001 +* @tc.desc: Update Stage Value. +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(ClipParaTest, UpdateStageValue_001, TestSize.Level0) +{ + auto curTime = duration_cast((system_clock::now() + minutes(2)).time_since_epoch()).count(); + ClipPara::GetInstance().InitMemberVariable(); + ClipPara::GetInstance().SetFirstStageValue(2); + ClipPara::GetInstance().SetSecondStageValue(0); + ClipPara::GetInstance().UpdateStageValue(static_cast(curTime), false); + auto firstStageValue1 = ClipPara::GetInstance().GetFirstStageValue(); + ASSERT_TRUE(firstStageValue1 == 2); + auto secondStageValue1 = ClipPara::GetInstance().GetSecondStageValue(); + ASSERT_TRUE(secondStageValue1 == 0); + ClipPara::GetInstance().UpdateStageValue(static_cast(curTime), true); + auto firstStageValue = ClipPara::GetInstance().GetFirstStageValue(); + ASSERT_TRUE(firstStageValue == 2); + auto secondStageValue = ClipPara::GetInstance().GetSecondStageValue(); + ASSERT_TRUE(secondStageValue == 0); + auto ret = ClipPara::GetInstance().GetPasted(); + ASSERT_TRUE(ret); +} + +/** +* @tc.name: UpdateStageValue_002 +* @tc.desc: Update Stage Value. +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(ClipParaTest, UpdateStageValue_002, TestSize.Level0) +{ + auto curTime = duration_cast((system_clock::now() + minutes(2)).time_since_epoch()).count(); + ClipPara::GetInstance().InitMemberVariable(); + ClipPara::GetInstance().SetPasted(true); + ClipPara::GetInstance().SetFirstStageValue(0); + ClipPara::GetInstance().SetSecondStageValue(2); + ClipPara::GetInstance().UpdateStageValue(static_cast(curTime), true); + auto firstStageValue = ClipPara::GetInstance().GetFirstStageValue(); + ASSERT_TRUE(firstStageValue == 0); + auto secondStageValue = ClipPara::GetInstance().GetSecondStageValue(); + ASSERT_TRUE(secondStageValue == 2); +} + +/** +* @tc.name: UpdateStageValue_003 +* @tc.desc: Update Stage Value. +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(ClipParaTest, UpdateStageValue_003, TestSize.Level0) +{ + auto curTime = duration_cast((system_clock::now() + minutes(2)).time_since_epoch()).count(); + ClipPara::GetInstance().InitMemberVariable(); + ClipPara::GetInstance().SetFirstStageValue(0); + ClipPara::GetInstance().SetSecondStageValue(2); + ClipPara::GetInstance().UpdateStageValue(static_cast(curTime), true); + auto firstStageValue = ClipPara::GetInstance().GetFirstStageValue(); + ASSERT_TRUE(firstStageValue == 2); + auto secondStageValue = ClipPara::GetInstance().GetSecondStageValue(); + ASSERT_TRUE(secondStageValue == 0); +} + +/** +* @tc.name: UpdateStageValue_004 +* @tc.desc: Update Stage Value. +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(ClipParaTest, UpdateStageValue_004, TestSize.Level0) +{ + auto curTime = duration_cast((system_clock::now()).time_since_epoch()).count(); + ClipPara::GetInstance().InitMemberVariable(); + ClipPara::GetInstance().SetPullEvent(true); + ClipPara::GetInstance().SetPasted(false); + ClipPara::GetInstance().SetFirstStageValue(1); + ClipPara::GetInstance().SetSecondStageValue(0); + ClipPara::GetInstance().UpdateStageValue(static_cast(curTime), true); + auto firstStageValue = ClipPara::GetInstance().GetFirstStageValue(); + ASSERT_TRUE(firstStageValue == 0); + auto secondStageValue = ClipPara::GetInstance().GetSecondStageValue(); + ASSERT_TRUE(secondStageValue == 0); +} +} \ No newline at end of file diff --git a/pasteboard/framework/test/src/dm_adapter_test.cpp b/pasteboard/framework/test/src/dm_adapter_test.cpp new file mode 100644 index 00000000..51a37724 --- /dev/null +++ b/pasteboard/framework/test/src/dm_adapter_test.cpp @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "device/dm_adapter.h" +#include "distributed_clip.h" +#include + +namespace OHOS::MiscServices { +using namespace testing::ext; +class DMAdapterTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void DMAdapterTest::SetUpTestCase(void) +{ +} + +void DMAdapterTest::TearDownTestCase(void) +{ +} + +void DMAdapterTest::SetUp(void) +{ +} + +void DMAdapterTest::TearDown(void) +{ +} + +/** +* @tc.name: GetLocalDeviceUdid +* @tc.desc: Get the local device udid. +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(DMAdapterTest, GetLocalDeviceUdid, TestSize.Level0) +{ + std::string bundleName = "com.example.myapplication"; + bool res = DMAdapter::GetInstance().Initialize(bundleName); + ASSERT_FALSE(res); + std::string device = "deviceTestName"; + auto fromDevice = DMAdapter::GetInstance().GetDeviceName(device); + ASSERT_FALSE(fromDevice.empty()); + auto &udid = DMAdapter::GetInstance().GetLocalDeviceUdid(); + ASSERT_TRUE(udid.empty()); +} + +/** +* @tc.name: GetLocalNetworkId +* @tc.desc: Get the local network id. +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(DMAdapterTest, GetLocalNetworkId, TestSize.Level0) +{ + std::string bundleName = "com.example.myapplication"; + bool res = DMAdapter::GetInstance().Initialize(bundleName); + ASSERT_FALSE(res); + auto networkId = DMAdapter::GetInstance().GetLocalNetworkId(); + ASSERT_FALSE(networkId.empty()); +} + +/** +* @tc.name: DistributedClipRegister +* @tc.desc: DistributedClip Register and Unregister. +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(DMAdapterTest, DistributedClipRegister, TestSize.Level0) +{ + DistributedClip *observer = new DistributedClip(); + DMAdapter::GetInstance().Register(observer); + DMAdapter::GetInstance().Unregister(observer); + ASSERT_TRUE(true); +} + +/** +* @tc.name: GetRemoteDeviceInfo +* @tc.desc: Get the remote device info. +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(DMAdapterTest, GetRemoteDeviceInfo, TestSize.Level0) +{ +#ifdef PB_DEVICE_MANAGER_ENABLE + DmDeviceInfo remoteDevice; + auto ret = DMAdapter::GetInstance().GetRemoteDeviceInfo("", remoteDevice); + ASSERT_TRUE(ret == -1); +#else + ASSERT_TRUE(true); +#endif +} + +/** +* @tc.name: GetUdidByNetworkId +* @tc.desc: Get Udid By NetworkId. +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(DMAdapterTest, GetUdidByNetworkId, TestSize.Level0) +{ + auto udid = DMAdapter::GetInstance().GetUdidByNetworkId(""); + ASSERT_TRUE(udid.empty()); +} +} diff --git a/pasteboard/framework/test/src/paste_data_test.cpp b/pasteboard/framework/test/src/paste_data_test.cpp new file mode 100644 index 00000000..ebcd2da2 --- /dev/null +++ b/pasteboard/framework/test/src/paste_data_test.cpp @@ -0,0 +1,919 @@ +/* +* Copyright (c) 2022-2023 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "copy_uri_handler.h" +#include "common/block_object.h" +#include "clip/clip_plugin.h" +#include "clip_factory.h" +#include "int_wrapper.h" +#include "paste_uri_handler.h" +#include "pasteboard_client.h" +#include "remote_file_share.h" +#include +#include + +namespace OHOS::MiscServices { +using namespace testing::ext; +using namespace testing; +using namespace OHOS::AAFwk; +using namespace OHOS::Media; +constexpr const int32_t INVALID_FD = -1; +constexpr const char *FILE_URI = "/data/test/resource/pasteboardTest.txt"; +class PasteDataTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void PasteDataTest::SetUpTestCase(void) +{ +} + +void PasteDataTest::TearDownTestCase(void) +{ +} + +void PasteDataTest::SetUp(void) +{ +} + +void PasteDataTest::TearDown(void) +{ +} + +ClipFactory::ClipFactory() +{ + ClipPlugin::RegCreator("distributed_clip", this); +} + +class UriHandlerMock : public UriHandler { +public: + UriHandlerMock() = default; + virtual ~UriHandlerMock() = default; + + MOCK_METHOD1(ToUri, std::string(int32_t fd)); + MOCK_METHOD2(ToFd, int32_t(const std::string &uri, bool isClient)); + MOCK_CONST_METHOD1(IsFile, bool(const std::string &uri)); +}; + +/** +* @tc.name: ReplaceShareUri001 +* @tc.desc: replace user id in share path +* @tc.type: FUNC +* @tc.require:AR000H5I1D +* @tc.author: baoyayong +*/ +HWTEST_F(PasteDataTest, ReplaceShareUri001, TestSize.Level0)__attribute__((no_sanitize("cfi"))) +{ + PasteData data; + PasteDataRecord::Builder builder(MIMETYPE_TEXT_URI); + std::string uriStr = "/data/storage/100/haps/caches/xxx.txt"; + auto uri = std::make_shared(uriStr); + builder.SetUri(uri); + auto record = builder.Build(); + + // mock + UriHandlerMock mock; + std::string mockUri = "/mnt/hmdfs/100/account/merge_view/services/psteboard_service/.share/xxx.txt"; + EXPECT_CALL(mock, ToUri(_)).WillRepeatedly(Return(mockUri)); + EXPECT_CALL(mock, ToFd(_, _)).WillRepeatedly(Return(2)); + EXPECT_CALL(mock, IsFile(_)).WillRepeatedly(Return(true)); + + data.AddRecord(record); + MessageParcel parcel; + data.WriteUriFd(parcel, mock); + bool result = data.ReadUriFd(parcel, mock); + EXPECT_TRUE(result); + EXPECT_EQ(mockUri, data.GetPrimaryUri()->ToString()); + data.ReplaceShareUri(200); + std::string mockUri2 = "/mnt/hmdfs/200/account/merge_view/services/psteboard_service/.share/xxx.txt"; + EXPECT_EQ(mockUri2, data.GetPrimaryUri()->ToString()); +} + +/** +* @tc.name: uriConvertTest001 +* @tc.desc: uri convert(in same app) +* @tc.type: FUNC +* @tc.require:AR000H5I1D +* @tc.author: chenyu +*/ +HWTEST_F(PasteDataTest, uriConvertTest001, TestSize.Level0)__attribute__((no_sanitize("cfi"))) +{ + PasteData data; + PasteDataRecord::Builder builder(MIMETYPE_TEXT_URI); + std::string uriStr = FILE_URI; + auto uri = std::make_shared(uriStr); + builder.SetUri(uri); + auto record = builder.Build(); + data.AddRecord(record); + + MessageParcel parcel; + CopyUriHandler copyHandler; + data.WriteUriFd(parcel, copyHandler); + bool result = data.ReadUriFd(parcel, copyHandler); + EXPECT_TRUE(result); + auto distributedUri = data.GetPrimaryUri()->ToString(); + EXPECT_FALSE(uriStr == distributedUri); + + MessageParcel parcel1; + PasteUriHandler pasteHandler; + int32_t fd = 5; + pasteHandler.ToUri(fd); + + data.SetLocalPasteFlag(true); + data.WriteUriFd(parcel1, pasteHandler); + result = data.ReadUriFd(parcel1, pasteHandler); + EXPECT_TRUE(result); + ASSERT_TRUE(data.GetPrimaryUri() != nullptr); + auto convertedUri = data.GetPrimaryUri()->ToString(); + EXPECT_EQ(distributedUri, convertedUri); + EXPECT_FALSE(uriStr == convertedUri); +} + +/** +* @tc.name: uriConvertTest002 +* @tc.desc: uri convert(in same app) +* @tc.type: FUNC +*/ +HWTEST_F(PasteDataTest, uriConvertTest002, TestSize.Level0) +{ + PasteUriHandler pasteHandler; + int32_t fd = -100; + std::string convertUri = pasteHandler.ToUri(fd); + EXPECT_TRUE(convertUri == ""); +} + +/** +* @tc.name: uriConvertTest003 +* @tc.desc: uri convert(in same app) +* @tc.type: FUNC +*/ +HWTEST_F(PasteDataTest, uriConvertTest003, TestSize.Level0) +{ + CopyUriHandler copyHandler; + int32_t fd = -100; + std::string convertUri = copyHandler.ToUri(fd); + EXPECT_TRUE(convertUri == ""); +} + +/** +* @tc.name: AddRecord001 +* @tc.desc: PasteDataRecord AddRecord +* @tc.type: FUNC +*/ +HWTEST_F(PasteDataTest, AddRecord001, TestSize.Level0) +{ + PasteData data; + PasteDataRecord::Builder builder(MIMETYPE_TEXT_URI); + std::string uriStr = FILE_URI; + auto uri = std::make_shared(uriStr); + builder.SetUri(uri); + auto record = builder.Build(); + EXPECT_TRUE(record != nullptr); + data.AddRecord(nullptr); + auto count = data.GetRecordCount(); + EXPECT_TRUE(count == 0); +} + +/** +* @tc.name: AddRecord002 +* @tc.desc: PasteDataRecord AddRecord +* @tc.type: FUNC +*/ +HWTEST_F(PasteDataTest, AddRecord002, TestSize.Level0) +{ + PasteData data; + PasteDataRecord::Builder builder(MIMETYPE_TEXT_URI); + std::string uriStr = FILE_URI; + auto uri = std::make_shared(uriStr); + builder.SetUri(uri); + auto record = builder.Build(); + data.AddRecord(*record); + auto count = data.GetRecordCount(); + EXPECT_TRUE(count == 1); +} + +/** +* @tc.name: GetRealPathFailed001 +* @tc.desc: GetRealPath Failed(realpath(inOriPath.c_str(), realPath) == nullptr) +* @tc.type: FUNC +* @tc.require: issuesI5Y6PO +* @tc.author: chenyu +*/ +HWTEST_F(PasteDataTest, GetRealPathFailed001, TestSize.Level0) +{ + std::string uriStr = "/data/storage/100/haps/caches/xxx.txt"; + PasteUriHandler pasteHandler; + auto ret = pasteHandler.ToFd(uriStr, true); + EXPECT_EQ(ret, INVALID_FD); +} + +/** +* @tc.name: GetRealPathFailed002 +* @tc.desc: GetRealPath Failed(inOriPath.size() > PATH_MAX) +* @tc.type: FUNC +* @tc.require: issuesI5Y6PO +* @tc.author: chenyu +*/ +HWTEST_F(PasteDataTest, GetRealPathFailed002, TestSize.Level0) +{ + std::string uriStr(PATH_MAX + 2, '*'); + PasteUriHandler pasteHandler; + auto ret = pasteHandler.ToFd(uriStr, true); + EXPECT_EQ(ret, INVALID_FD); +} + +/** +* @tc.name: MaxLength001 +* @tc.desc: PasteDataRecord: maxLength NewHtmlRecord +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(PasteDataTest, MaxLength001, TestSize.Level0) +{ + int maxLength = 20 * 1024 * 1024; + std::string res = "hello"; + std::string temp = "world"; + for (int i = 0; i < maxLength; i++) + { + res += temp; + } + std::string htmlText = "
" + res + "
"; + auto record = PasteboardClient::GetInstance()->CreateHtmlTextRecord(htmlText); + ASSERT_TRUE(record == nullptr); +} + +/** +* @tc.name: MaxLength002 +* @tc.desc: PasteDataRecord: maxLength NewPlaintTextRecord +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(PasteDataTest, MaxLength002, TestSize.Level0) +{ + int maxLength = 20 * 1024 * 1024; + std::string plainText = "hello"; + std::string temp = "world"; + for (int i = 0; i < maxLength; i++) + { + plainText += temp; + } + auto record = PasteboardClient::GetInstance()->CreatePlainTextRecord(plainText); + ASSERT_TRUE(record == nullptr); +} + +/** +* @tc.name: ConvertToText001 +* @tc.desc: PasteDataRecord: ConvertToText htmlText +* @tc.type: FUNC +* @tc.require: AR000HEECD +* @tc.author: chenyu +*/ +HWTEST_F(PasteDataTest, ConvertToText001, TestSize.Level0) +{ + std::string htmlText = "
"; + auto record = PasteboardClient::GetInstance()->CreateHtmlTextRecord(htmlText); + ASSERT_TRUE(record != nullptr); + auto text = record->ConvertToText(); + EXPECT_EQ(text, htmlText); +} + +/** +* @tc.name: ConvertToText002 +* @tc.desc: PasteDataRecord: ConvertToText plainText +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(PasteDataTest, ConvertToText002, TestSize.Level0) +{ + std::string plainText = "paste record test"; + auto record = PasteboardClient::GetInstance()->CreatePlainTextRecord(plainText); + ASSERT_TRUE(record != nullptr); + auto text = record->ConvertToText(); + EXPECT_EQ(text, plainText); +} + +/** +* @tc.name: ConvertToText003 +* @tc.desc: PasteDataRecord: ConvertToText uri +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(PasteDataTest, ConvertToText003, TestSize.Level0) +{ + OHOS::Uri uri("uri"); + auto record = PasteboardClient::GetInstance()->CreateUriRecord(uri); + ASSERT_TRUE(record != nullptr); + auto text = record->ConvertToText(); + EXPECT_EQ(text, uri.ToString()); +} + +/** +* @tc.name: ConvertToText004 +* @tc.desc: PasteDataRecord: ConvertToText uri +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(PasteDataTest, ConvertToText004, TestSize.Level0) +{ + uint32_t color[100] = { 3, 7, 9, 9, 7, 6 }; + InitializationOptions opts = { { 5, 7 }, PixelFormat::ARGB_8888 }; + std::unique_ptr pixelMap = PixelMap::Create(color, 100, opts); + std::shared_ptr pixelMapIn = move(pixelMap); + auto record = PasteboardClient::GetInstance()->CreatePixelMapRecord(pixelMapIn); + ASSERT_TRUE(record != nullptr); + auto text = record->ConvertToText(); + EXPECT_EQ(text, ""); +} + +/** +* @tc.name: GetPasteDataMsg001 +* @tc.desc: PasteData: GetPrimaryMimeType is nullptr and so on +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(PasteDataTest, GetPasteDataMsg001, TestSize.Level0) +{ + std::string plainText1 = "helloWorld"; + auto pasteData = PasteboardClient::GetInstance()->CreatePlainTextData(plainText1); + ASSERT_TRUE(pasteData != nullptr); + auto newPrimaryPixelMap = pasteData->GetPrimaryPixelMap(); + ASSERT_TRUE(newPrimaryPixelMap == nullptr); + auto newPrimaryMimeType = pasteData->GetPrimaryMimeType(); + ASSERT_TRUE(newPrimaryMimeType != nullptr); + auto newPasteData = std::make_shared(); + auto newPrimaryMimeType2 = newPasteData->GetPrimaryMimeType(); + ASSERT_TRUE(newPrimaryMimeType2 == nullptr); + std::string plainText2 = "plain text"; + auto record = PasteboardClient::GetInstance()->CreatePlainTextRecord(plainText2); + ASSERT_TRUE(record != nullptr); + ASSERT_FALSE(pasteData->ReplaceRecordAt(1000, record)); +} + +/** +* @tc.name: GetPasteDataMsg002 +* @tc.desc: PasteData: GetPrimaryWant is nullptr and so on +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(PasteDataTest, GetPasteDataMsg002, TestSize.Level0) +{ + uint32_t color[100] = { 3, 7, 9, 9, 7, 6 }; + InitializationOptions opts = { { 5, 7 }, PixelFormat::ARGB_8888 }; + std::unique_ptr pixelMap = PixelMap::Create(color, sizeof(color) / sizeof(color[0]), opts); + std::shared_ptr pixelMapIn = move(pixelMap); + auto newPasteData = PasteboardClient::GetInstance()->CreatePixelMapData(pixelMapIn); + ASSERT_TRUE(newPasteData != nullptr); + auto pixMap = newPasteData->GetPrimaryPixelMap(); + ASSERT_TRUE(pixMap != nullptr); + auto primaryWant = newPasteData->GetPrimaryWant(); + ASSERT_TRUE(primaryWant == nullptr); + auto primaryText = newPasteData->GetPrimaryText(); + ASSERT_TRUE(primaryText == nullptr); + auto primaryUri = newPasteData->GetPrimaryUri(); + ASSERT_TRUE(primaryUri == nullptr); + auto record = newPasteData->GetRecordAt(1); + ASSERT_TRUE(record == nullptr); + auto res1 = newPasteData->RemoveRecordAt(1); + ASSERT_FALSE(res1); + std::string mimeType = "text/plain"; + ASSERT_FALSE(newPasteData->HasMimeType(mimeType)); +} + +/** +* @tc.name: ShareOptionToString001 +* @tc.desc: PasteData: ShareOptionToString +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(PasteDataTest, ShareOptionToString001, TestSize.Level0) +{ + std::string shareOption1; + PasteData::ShareOptionToString(ShareOption::InApp, shareOption1); + ASSERT_TRUE(shareOption1 == "InAPP"); + std::string shareOption2; + PasteData::ShareOptionToString(ShareOption::LocalDevice, shareOption2); + ASSERT_TRUE(shareOption2 == "LocalDevice"); + std::string shareOption3; + PasteData::ShareOptionToString(ShareOption::CrossDevice, shareOption3); + ASSERT_TRUE(shareOption3 == "CrossDevice"); +} + +/** +* @tc.name: SetInvalid001 +* @tc.desc: PasteData: SetInvalid001 +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(PasteDataTest, SetInvalid001, TestSize.Level0) +{ + bool result = true; + std::shared_ptr pasteData = std::make_shared(); + pasteData->SetInvalid(); + result = pasteData->IsValid(); + ASSERT_FALSE(result); +} + +/** +* @tc.name: SetLocalOnly001 +* @tc.desc: PasteData: SetLocalOnly +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(PasteDataTest, SetLocalOnly001, TestSize.Level0) +{ + bool result = false; + std::shared_ptr pasteData = std::make_shared(); + pasteData->SetLocalOnly(true); + result = pasteData->GetLocalOnly(); + ASSERT_TRUE(result); +} + +/** +* @tc.name: SetAddition001 +* @tc.desc: PasteData: SetAddition +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(PasteDataTest, SetAddition001, TestSize.Level0) +{ + std::string plainText = "plain text"; + auto pasteData = PasteboardClient::GetInstance()->CreatePlainTextData(plainText); + size_t fileSize = 0; + pasteData->SetAddition(PasteData::REMOTE_FILE_SIZE, AAFwk::Integer::Box(fileSize)); + AAFwk::WantParams additions; + pasteData->SetAdditions(additions); + ASSERT_TRUE(pasteData != nullptr); +} + +/** +* @tc.name: SetRemote001 +* @tc.desc: PasteData: SetRemote +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(PasteDataTest, SetRemote001, TestSize.Level0) +{ + bool isRemote = false; + std::string plainText = "plain text"; + auto pasteData = PasteboardClient::GetInstance()->CreatePlainTextData(plainText); + isRemote = true; + pasteData->SetRemote(isRemote); + bool result = pasteData->IsRemote(); + ASSERT_TRUE(result); +} + +/** +* @tc.name: SetOrginAuthority001 +* @tc.desc: PasteData: SetOrginAuthority +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(PasteDataTest, SetOrginAuthority001, TestSize.Level0) +{ + std::string plainText = "plain text"; + std::string bundleName = "com.example.myapplication"; + auto pasteData = PasteboardClient::GetInstance()->CreatePlainTextData(plainText); + pasteData->SetBundleName(bundleName); + pasteData->SetOrginAuthority(bundleName); + std::string getBundleName = pasteData->GetBundleName(); + std::string getOrginAuthority = pasteData->GetOrginAuthority(); + ASSERT_TRUE(getBundleName == bundleName); + ASSERT_TRUE(getOrginAuthority == bundleName); + std::string time = "2023-08-09"; + pasteData->SetTime(time); + std::string getTime = pasteData->GetTime(); + ASSERT_TRUE(getTime == time); +} + +/** +* @tc.name: GetConvertUri001 +* @tc.desc: PasteDataRecord: GetConvertUri +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(PasteDataTest, GetConvertUri001, TestSize.Level0) +{ + std::vector arrayBuffer(46); + arrayBuffer = { 2, 7, 6, 8, 9 }; + std::string mimeType = "image/jpg"; + auto pasteDataRecord = PasteboardClient::GetInstance()->CreateKvRecord(mimeType, arrayBuffer); + ASSERT_TRUE(pasteDataRecord != nullptr); + std::string convertUri_ = "/mnt/hmdfs/"; + pasteDataRecord->SetConvertUri(convertUri_); + std::string result = pasteDataRecord->GetConvertUri(); + ASSERT_TRUE(result == convertUri_); + std::string newUriStr = "/mnt/hmdfs/test"; + pasteDataRecord->SetUri(std::make_shared(newUriStr)); + std::shared_ptr uri = pasteDataRecord->GetUri(); + ASSERT_TRUE(uri != nullptr); + std::shared_ptr getOriginUri = pasteDataRecord->GetOrginUri(); + ASSERT_TRUE(getOriginUri != nullptr); +} + +/** +* @tc.name: GetConvertUri002 +* @tc.desc: PasteDataRecord: GetConvertUri +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(PasteDataTest, GetConvertUri002, TestSize.Level0) +{ + std::vector arrayBuffer(46); + arrayBuffer = { 2, 7, 6, 8, 9 }; + std::string mimeType = "image/jpg"; + auto pasteDataRecord = PasteboardClient::GetInstance()->CreateKvRecord(mimeType, arrayBuffer); + ASSERT_TRUE(pasteDataRecord != nullptr); + std::string convertUri_ = ""; + pasteDataRecord->SetConvertUri(convertUri_); + std::string result = pasteDataRecord->GetConvertUri(); + ASSERT_TRUE(result == convertUri_); + pasteDataRecord->ReplaceShareUri(200); + std::string result2 = pasteDataRecord->GetConvertUri(); + ASSERT_TRUE(result2 == convertUri_); +} + +/** +* @tc.name: HasGrantUriPermission001 +* @tc.desc: PasteDataRecord: HasGrantUriPermission +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(PasteDataTest, HasGrantUriPermission001, TestSize.Level0) +{ + std::vector arrayBuffer(46); + arrayBuffer = { 1, 2, 6, 8, 9 }; + std::string mimeType = "image/jpg"; + auto pasteDataRecord = PasteboardClient::GetInstance()->CreateKvRecord(mimeType, arrayBuffer); + ASSERT_TRUE(pasteDataRecord != nullptr); + pasteDataRecord->SetGrantUriPermission(true); + auto hasGrantUriPermission_ = pasteDataRecord->HasGrantUriPermission(); + ASSERT_TRUE(hasGrantUriPermission_); +} + +/** +* @tc.name: LoadSystemAbilityFail001 +* @tc.desc: PasteDataRecord: LoadSystemAbilityFail +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(PasteDataTest, LoadSystemAbilityFail001, TestSize.Level0) +{ + std::vector arrayBuffer(46); + std::string mimeType = "image/jpg"; + arrayBuffer = { 1, 2, 3, 4, 6 }; + PasteboardClient::GetInstance()->LoadSystemAbilityFail(); + auto pasteDataRecord = PasteboardClient::GetInstance()->CreateKvRecord(mimeType, arrayBuffer); + ASSERT_TRUE(pasteDataRecord != nullptr); +} + +/** +* @tc.name: LoadSystemAbilitySuccess001 +* @tc.desc: PasteDataRecord: LoadSystemAbilitySuccess +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(PasteDataTest, LoadSystemAbilitySuccess001, TestSize.Level0) +{ + std::vector arrayBuffer(46); + std::string mimeType = "image/jpg"; + arrayBuffer = { 1, 2, 3, 4, 6 }; + sptr remoteObject = nullptr; + PasteboardClient::GetInstance()->LoadSystemAbilitySuccess(remoteObject); + auto pasteDataRecord = PasteboardClient::GetInstance()->CreateKvRecord(mimeType, arrayBuffer); + ASSERT_TRUE(pasteDataRecord != nullptr); +} + +/** +* @tc.name: SetInterval001 +* @tc.desc: BlockObject: SetInterval +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(PasteDataTest, SetInterval001, TestSize.Level0) +{ + uint32_t POPUP_INTERVAL = 1; + auto block = std::make_shared>>(POPUP_INTERVAL); + std::shared_ptr pasteData = std::make_shared(); + block->SetValue(pasteData); + block->SetInterval(POPUP_INTERVAL); + auto value = block->GetValue(); + EXPECT_TRUE(value != nullptr); +} + +/** +* @tc.name: ClipPlugin001 +* @tc.desc: API_EXPORT: ClipPlugin +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(PasteDataTest, ClipPlugin001, TestSize.Level0) +{ + std::string PLUGIN_NAME_VAL = "distributed_clip"; + auto release = [&PLUGIN_NAME_VAL, this](ClipPlugin *plugin) { + ClipPlugin::DestroyPlugin(PLUGIN_NAME_VAL, plugin); + }; + auto clipPlugin_ = std::shared_ptr(ClipPlugin::CreatePlugin(PLUGIN_NAME_VAL), release); + ClipPlugin::Factory *factory = nullptr; + auto result = ClipPlugin::RegCreator(PLUGIN_NAME_VAL, factory); + EXPECT_TRUE(result); + auto userId = 10000; + auto events1 = clipPlugin_->GetTopEvents(1, userId); + EXPECT_TRUE(events1.size() == 0); + auto events2 = clipPlugin_->GetTopEvents(1); + EXPECT_TRUE(events2.size() == 0); + clipPlugin_->Clear(); + clipPlugin_->Clear(userId); +} + +/** +* @tc.name: ClipPlugin002 +* @tc.desc: API_EXPORT: ClipPlugin +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(PasteDataTest, ClipPlugin002, TestSize.Level0) +{ + std::string PLUGIN_NAME_VAL = "distributed_clip"; + auto release = [&PLUGIN_NAME_VAL, this](ClipPlugin *plugin) { + ClipPlugin::DestroyPlugin(PLUGIN_NAME_VAL, plugin); + }; + auto clipPlugin_ = std::shared_ptr(ClipPlugin::CreatePlugin(PLUGIN_NAME_VAL), release); + ClipPlugin::Factory *factory = new ClipFactory(); + auto result = ClipPlugin::RegCreator(PLUGIN_NAME_VAL, factory); + EXPECT_FALSE(result); + auto userId = 3701; + auto events1 = clipPlugin_->GetTopEvents(1, userId); + EXPECT_TRUE(events1.size() == 0); + clipPlugin_->Clear(userId); +} + +/** +* @tc.name: ClipPlugin003 +* @tc.desc: API_EXPORT: ClipPlugin +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(PasteDataTest, ClipPlugin003, TestSize.Level0) +{ + ClipPlugin::GlobalEvent event1; + event1.seqId = 0; + event1.deviceId = "test_device_id"; + event1.user = 0; + ClipPlugin::GlobalEvent event2; + event2.seqId = 0; + event2.deviceId = "test_device_id"; + event2.user = 1; + EXPECT_TRUE(event1 == event2); +} + +/** +* @tc.name: ClipPlugin004 +* @tc.desc: API_EXPORT: ClipPlugin +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(PasteDataTest, ClipPlugin004, TestSize.Level0) +{ + ClipPlugin::GlobalEvent event1; + event1.seqId = 0; + event1.deviceId = "test_device_id"; + event1.user = 0; + ClipPlugin::GlobalEvent event2; + event2.seqId = 0; + event2.deviceId = "test_device_id1"; + event2.user = 1; + EXPECT_FALSE(event1 == event2); +} + +/** +* @tc.name: ClipPlugin005 +* @tc.desc: API_EXPORT: ClipPlugin +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(PasteDataTest, ClipPlugin005, TestSize.Level0) +{ + ClipPlugin::GlobalEvent event1; + event1.seqId = 0; + event1.deviceId = "test_device_id"; + event1.user = 0; + ClipPlugin::GlobalEvent event2; + event2.seqId = 1; + event2.deviceId = "test_device_id"; + event2.user = 1; + EXPECT_FALSE(event1 == event2); +} + +/** +* @tc.name: PasteDataOperator001 +* @tc.desc: PasteData: operator +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(PasteDataTest, PasteDataOperator001, TestSize.Level0) +{ + PasteData data1; + PasteDataRecord::Builder builder1(MIMETYPE_TEXT_URI); + std::string uriStr1 = FILE_URI; + auto uri1 = std::make_shared(uriStr1); + builder1.SetUri(uri1); + auto record1 = builder1.Build(); + data1.AddRecord(record1); + std::string bundleName1 = "com.example.myapplication"; + data1.SetOrginAuthority(bundleName1); + + PasteData data2; + PasteDataRecord::Builder builder2(MIMETYPE_TEXT_URI); + std::string uriStr2 = FILE_URI; + auto uri2 = std::make_shared(uriStr2); + builder2.SetUri(uri2); + auto record2 = builder2.Build(); + data2.AddRecord(record2); + std::string bundleName2 = "com.example.myapplication"; + data2.SetOrginAuthority(bundleName2); + + ASSERT_TRUE(data1.GetBundleName() == data2.GetBundleName()); +} + +/** +* @tc.name: GetShareOption001 +* @tc.desc: +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(PasteDataTest, GetShareOption001, TestSize.Level0) +{ + std::string plainText = "plain text"; + auto pasteData = PasteboardClient::GetInstance()->CreatePlainTextData(plainText); + ASSERT_TRUE(pasteData != nullptr); + ShareOption option = InApp; + pasteData->SetShareOption(option); + auto result = pasteData->GetShareOption(); + ASSERT_TRUE(result == InApp); +} + +/** +* @tc.name: AddKvRecord001 +* @tc.desc: +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(PasteDataTest, AddKvRecord001, TestSize.Level0) +{ + PasteData data; + std::vector arrayBuffer(46); + arrayBuffer = { 2, 7, 6, 8, 9 }; + std::string mimeType = "image/jpg"; + data.AddKvRecord(mimeType, arrayBuffer); + ASSERT_TRUE(data.GetRecordCount() > 0); +} + +/** +* @tc.name: GetProperty001 +* @tc.desc: +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(PasteDataTest, GetProperty001, TestSize.Level0) +{ + std::string plainText = "plain text"; + auto pasteData = PasteboardClient::GetInstance()->CreatePlainTextData(plainText); + ASSERT_TRUE(pasteData != nullptr); + PasteDataProperty property = pasteData->GetProperty(); + ASSERT_TRUE(property.tokenId == 0); +} + +/** +* @tc.name: SetProperty001 +* @tc.desc: +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(PasteDataTest, SetProperty001, TestSize.Level0) +{ + std::string plainText = "plain text"; + auto pasteData = PasteboardClient::GetInstance()->CreatePlainTextData(plainText); + ASSERT_TRUE(pasteData != nullptr); + PasteDataProperty property; + property.tokenId = 1; + pasteData->SetProperty(property); + PasteDataProperty pasteDataProperty = pasteData->GetProperty(); + ASSERT_TRUE(pasteDataProperty.tokenId == 1); +} + +/** +* @tc.name: SetShareOption001 +* @tc.desc: +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(PasteDataTest, SetShareOption001, TestSize.Level0) +{ + std::string plainText = "plain text"; + auto pasteData = PasteboardClient::GetInstance()->CreatePlainTextData(plainText); + ASSERT_TRUE(pasteData != nullptr); + ShareOption option = LocalDevice; + pasteData->SetShareOption(option); + auto result = pasteData->GetShareOption(); + ASSERT_TRUE(result == LocalDevice); +} + +/** +* @tc.name: SetTokenId001 +* @tc.desc: +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(PasteDataTest, SetTokenId001, TestSize.Level0) +{ + std::string plainText = "plain text"; + auto pasteData = PasteboardClient::GetInstance()->CreatePlainTextData(plainText); + ASSERT_TRUE(pasteData != nullptr); + uint32_t tokenId = 1; + pasteData->SetTokenId(tokenId); + auto result = pasteData->GetTokenId(); + ASSERT_TRUE(result == 1); +} + +/** +* @tc.name: IsDraggedData001 +* @tc.desc: +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(PasteDataTest, IsDraggedData001, TestSize.Level0) +{ + std::string plainText = "plain text"; + auto pasteData = PasteboardClient::GetInstance()->CreatePlainTextData(plainText); + ASSERT_TRUE(pasteData != nullptr); + bool isDraggedData = false; + pasteData->SetDraggedDataFlag(isDraggedData); + auto result = pasteData->IsDraggedData(); + ASSERT_FALSE(result); +} + +/** +* @tc.name: SetDraggedDataFlag001 +* @tc.desc: +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(PasteDataTest, SetDraggedDataFlag001, TestSize.Level0) +{ + std::string plainText = "plain text"; + auto pasteData = PasteboardClient::GetInstance()->CreatePlainTextData(plainText); + ASSERT_TRUE(pasteData != nullptr); + bool isDraggedData = true; + pasteData->SetDraggedDataFlag(isDraggedData); + auto result = pasteData->IsDraggedData(); + ASSERT_TRUE(result); +} +} // namespace OHOS::MiscServices diff --git a/pasteboard/framework/test/src/pasteboard_client_test.cpp b/pasteboard/framework/test/src/pasteboard_client_test.cpp new file mode 100644 index 00000000..45f56d5e --- /dev/null +++ b/pasteboard/framework/test/src/pasteboard_client_test.cpp @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2023-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "pasteboard_client.h" +#include + +namespace OHOS::MiscServices { +using namespace testing::ext; +using namespace testing; +using namespace OHOS::Media; +class PasteboardClientTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void PasteboardClientTest::SetUpTestCase(void) +{ +} + +void PasteboardClientTest::TearDownTestCase(void) +{ +} + +void PasteboardClientTest::SetUp(void) +{ +} + +void PasteboardClientTest::TearDown(void) +{ +} + +/** +* @tc.name: IsRemoteData001 +* @tc.desc: pasteData is local data. +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(PasteboardClientTest, IsRemoteData001, TestSize.Level0) +{ + std::string plainText = "plain text"; + auto pasteData = PasteboardClient::GetInstance()->CreatePlainTextData(plainText); + PasteboardClient::GetInstance()->SetPasteData(*pasteData); + bool ret = PasteboardClient::GetInstance()->IsRemoteData(); + ASSERT_FALSE(ret); +} + +/** +* @tc.name: IsRemoteData002 +* @tc.desc: pasteData is remote data. +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(PasteboardClientTest, IsRemoteData002, TestSize.Level0) +{ + std::string plainText = "plain text"; + auto pasteData = PasteboardClient::GetInstance()->CreatePlainTextData(plainText); + pasteData->SetRemote(true); + PasteboardClient::GetInstance()->SetPasteData(*pasteData); + bool ret = PasteboardClient::GetInstance()->IsRemoteData(); + ASSERT_TRUE(ret); +} + +/** +* @tc.name: HasDataType001 +* @tc.desc: data type is MIMETYPE_TEXT_PLAIN. +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(PasteboardClientTest, HasDataType001, TestSize.Level0) +{ + std::string plainText = "helloWorld"; + auto newData = PasteboardClient::GetInstance()->CreatePlainTextData(plainText); + PasteboardClient::GetInstance()->SetPasteData(*newData); + auto ret = PasteboardClient::GetInstance()->HasDataType(MIMETYPE_TEXT_PLAIN); + ASSERT_TRUE(ret); + auto result = PasteboardClient::GetInstance()->HasDataType(MIMETYPE_TEXT_URI); + ASSERT_FALSE(result); +} + +/** +* @tc.name: HasDataType002 +* @tc.desc: data type is MIMETYPE_TEXT_HTML. +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(PasteboardClientTest, HasDataType002, TestSize.Level0) +{ + std::string htmlText = "
helloWorld
"; + auto newPasteData = PasteboardClient::GetInstance()->CreateHtmlData(htmlText); + PasteboardClient::GetInstance()->SetPasteData(*newPasteData); + auto ret = PasteboardClient::GetInstance()->HasDataType(MIMETYPE_TEXT_HTML); + ASSERT_TRUE(ret); + auto result = PasteboardClient::GetInstance()->HasDataType(MIMETYPE_TEXT_PLAIN); + ASSERT_FALSE(result); +} + +/** +* @tc.name: HasDataType003 +* @tc.desc: data type is MIMETYPE_TEXT_URI +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(PasteboardClientTest, HasDataType003, TestSize.Level0) +{ + OHOS::Uri uri("uri"); + auto newPasteData = PasteboardClient::GetInstance()->CreateUriData(uri); + PasteboardClient::GetInstance()->SetPasteData(*newPasteData); + auto ret = PasteboardClient::GetInstance()->HasDataType(MIMETYPE_TEXT_URI); + ASSERT_TRUE(ret); + auto result = PasteboardClient::GetInstance()->HasDataType(MIMETYPE_TEXT_PLAIN); + ASSERT_FALSE(result); +} + +/** +* @tc.name: HasDataType004 +* @tc.desc: data type is MIMETYPE_PIXELMAP +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(PasteboardClientTest, HasDataType004, TestSize.Level0) +{ + uint32_t color[100] = { 3, 7, 9, 9, 7, 6 }; + InitializationOptions opts = { { 5, 7 }, PixelFormat::ARGB_8888 }; + std::unique_ptr pixelMap = PixelMap::Create(color, sizeof(color) / sizeof(color[0]), opts); + std::shared_ptr pixelMapIn = move(pixelMap); + auto newPasteData = PasteboardClient::GetInstance()->CreatePixelMapData(pixelMapIn); + PasteboardClient::GetInstance()->SetPasteData(*newPasteData); + auto ret = PasteboardClient::GetInstance()->HasDataType(MIMETYPE_PIXELMAP); + ASSERT_TRUE(ret); + auto result = PasteboardClient::GetInstance()->HasDataType(MIMETYPE_TEXT_URI); + ASSERT_FALSE(result); +} + +/** +* @tc.name: GetDataSource001 +* @tc.desc: Get the source of the data. +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(PasteboardClientTest, GetDataSource001, TestSize.Level0) +{ + std::string plainText = "helloWorld"; + auto newData = PasteboardClient::GetInstance()->CreatePlainTextData(plainText); + PasteboardClient::GetInstance()->SetPasteData(*newData); + std::string bundleName; + PasteboardClient::GetInstance()->GetDataSource(bundleName); + EXPECT_FALSE(bundleName.empty()); +} +} // namespace OHOS::MiscServices \ No newline at end of file diff --git a/pasteboard/framework/test/src/serializable_test.cpp b/pasteboard/framework/test/src/serializable_test.cpp new file mode 100644 index 00000000..ac297419 --- /dev/null +++ b/pasteboard/framework/test/src/serializable_test.cpp @@ -0,0 +1,381 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "config.h" +#include "pasteboard_hilog.h" +#include "serializable.h" +#include + +namespace OHOS::DistributedData { +using namespace testing::ext; +using namespace OHOS::MiscServices; +class SerializableTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + void CreateConfig(Config &config); + void CreateComponent(Config::Component &component, int32_t index); +}; + +void SerializableTest::SetUpTestCase(void) +{ +} + +void SerializableTest::TearDownTestCase(void) +{ +} + +void SerializableTest::SetUp(void) +{ +} + +void SerializableTest::TearDown(void) +{ +} + +void SerializableTest::CreateComponent(Config::Component &component, int32_t index) +{ + component.description = "description" + std::to_string(index); + component.lib = "lib" + std::to_string(index); + component.constructor = "constructor" + std::to_string(index); + component.destructor = "destructor" + std::to_string(index); + component.params = "params" + std::to_string(index); +} + +void SerializableTest::CreateConfig(Config &config) +{ + config.processLabel = "processLabel"; + config.version = "version"; + config.features = { "feature1", "feature2" }; + config.plugins = { "plugin1", "plugin2" }; + Config::Component component1; + Config::Component component2; + int32_t index = 0; + CreateComponent(component1, index++); + CreateComponent(component2, index++); + config.components = { component1, component2 }; +} + +/** +* @tc.name: SerializableTest001 +* @tc.desc: test serializable with invalid jsonStr . +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(SerializableTest, SerializableTest001, TestSize.Level0) +{ + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_INNERKIT, "Start."); + std::string jsonStr; + auto json = Serializable::ToJson(jsonStr); + ASSERT_TRUE(cJSON_IsNull(&json)); + + Config config; + auto ret = config.Unmarshall(jsonStr); + ASSERT_FALSE(ret); + + jsonStr = "{ a }"; + json = Serializable::ToJson(jsonStr); + ASSERT_TRUE(cJSON_IsNull(&json)); + + ret = config.Unmarshall(jsonStr); + ASSERT_FALSE(ret); + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_INNERKIT, "End."); +} + +/** +* @tc.name: SerializableTest002 +* @tc.desc: test serializable with valid jsonStr . +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(SerializableTest, SerializableTest002, TestSize.Level0) +{ + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_INNERKIT, "Start."); + + std::vector vec = { 1, 2, 3, 4, 5 }; + std::string jsonStr = "{\n" + " \"param1\": 2, \n" + " \"param2\": 3, \n" + " \"param3\": 4, \n" + " \"param4\": true, \n" + " \"param5\": [1, 2, 3, 4, 5] \n" + "}"; + + uint32_t res1; + int32_t res2; + int64_t res3; + bool res4; + std::vector res5; + + auto node = Serializable::ToJson(jsonStr); + + auto ret = Serializable::GetValue(node, GET_NAME(param1), res1); + ASSERT_TRUE(ret); + ASSERT_EQ(res1, 2); + ret = Serializable::GetValue(node, GET_NAME(param2), res2); + ASSERT_TRUE(ret); + ASSERT_EQ(res2, 3); + ret = Serializable::GetValue(node, GET_NAME(param3), res3); + ASSERT_TRUE(ret); + ASSERT_EQ(res3, 4); + ret = Serializable::GetValue(node, GET_NAME(param4), res4); + ASSERT_TRUE(ret); + ASSERT_TRUE(res4); + ret = Serializable::GetValue(node, GET_NAME(param5), res5); + ASSERT_TRUE(ret); + ASSERT_EQ(res5.size(), vec.size()); + for (uint64_t i = 0; i < res5.size(); i++) { + ASSERT_EQ(res5[i], vec[i]); + } + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_INNERKIT, "End."); +} + +/** +* @tc.name: SerializableTest003 +* @tc.desc: test serializable GetValue and SetValue with invalid string value . +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(SerializableTest, SerializableTest003, TestSize.Level0) +{ + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_INNERKIT, "Start."); + std::string jsonStr = R"({"key":null})"; + auto json = Serializable::ToJson(jsonStr); + std::string value; + auto ret = Serializable::GetValue(json, "key", value); + ASSERT_FALSE(ret); + + jsonStr = R"({"key":1})"; + json = Serializable::ToJson(jsonStr); + ret = Serializable::GetValue(json, "key", value); + ASSERT_FALSE(ret); + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_INNERKIT, "End."); +} + +/** +* @tc.name: SerializableTest004 +* @tc.desc: test serializable GetValue and SetValue with invalid uint32_t value . +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(SerializableTest, SerializableTest004, TestSize.Level0) +{ + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_INNERKIT, "Start."); + std::string jsonStr = R"({"key":null})"; + auto json = Config::ToJson(jsonStr); + uint32_t value; + auto ret = Serializable::GetValue(json, "key", value); + ASSERT_FALSE(ret); + + jsonStr = R"({"key":"1"})"; + json = Serializable::ToJson(jsonStr); + ret = Serializable::GetValue(json, "key", value); + ASSERT_FALSE(ret); + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_INNERKIT, "End."); +} + +/** +* @tc.name: SerializableTest005 +* @tc.desc: test serializable GetValue and SetValue with invalid int32_t value . +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(SerializableTest, SerializableTest005, TestSize.Level0) +{ + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_INNERKIT, "Start."); + std::string jsonStr = R"({"key":null})"; + auto json = Config::ToJson(jsonStr); + int32_t value; + auto ret = Serializable::GetValue(json, "key", value); + ASSERT_FALSE(ret); + + jsonStr = R"({"key":"1"})"; + json = Serializable::ToJson(jsonStr); + ret = Serializable::GetValue(json, "key", value); + ASSERT_FALSE(ret); + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_INNERKIT, "End."); +} + +/** +* @tc.name: SerializableTest006 +* @tc.desc: test serializable GetValue and SetValue with invalid int64_t value . +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(SerializableTest, SerializableTest006, TestSize.Level0) +{ + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_INNERKIT, "Start."); + std::string jsonStr = R"({"key":null})"; + auto json = Serializable::ToJson(jsonStr); + int64_t value; + auto ret = Serializable::GetValue(json, "key", value); + ASSERT_FALSE(ret); + + jsonStr = R"({"key":"1"})"; + json = Serializable::ToJson(jsonStr); + ret = Serializable::GetValue(json, "key", value); + ASSERT_FALSE(ret); + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_INNERKIT, "End."); +} + +/** +* @tc.name: SerializableTest007 +* @tc.desc: test serializable GetValue and SetValue with invalid bool value . +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(SerializableTest, SerializableTest007, TestSize.Level0) +{ + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_INNERKIT, "Start."); + std::string jsonStr = R"({"key":null})"; + auto json = Serializable::ToJson(jsonStr); + bool value; + auto ret = Serializable::GetValue(json, "key", value); + ASSERT_FALSE(ret); + + jsonStr = R"({"key":1})"; + json = Serializable::ToJson(jsonStr); + ret = Serializable::GetValue(json, "key", value); + ASSERT_FALSE(ret); + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_INNERKIT, "End."); +} + +/** +* @tc.name: SerializableTest008 +* @tc.desc: test serializable GetValue and SetValue with invalid std::vector value . +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(SerializableTest, SerializableTest008, TestSize.Level0) +{ + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_INNERKIT, "Start."); + std::string jsonStr = R"({"key":null})"; + auto json = Serializable::ToJson(jsonStr); + std::vector value; + auto ret = Serializable::GetValue(json, "key", value); + ASSERT_FALSE(ret); + + jsonStr = R"({"key":"{1, 2, 3}"})"; + json = Serializable::ToJson(jsonStr); + ret = Serializable::GetValue(json, "key", value); + ASSERT_FALSE(ret); + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_INNERKIT, "End."); +} + +/** +* @tc.name: SerializableTest009 +* @tc.desc: test serializable SetValue with valid value. +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(SerializableTest, SerializableTest009, TestSize.Level0) +{ + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_INNERKIT, "Start."); + uint32_t param1 = 2; + int32_t param2 = 3; + int64_t param3 = 4; + bool param4 = false; + std::vector param5 = { 1, 2, 3, 4, 5 }; + Config config; + CreateConfig(config); + + auto node = config.Marshall(); + ASSERT_FALSE(cJSON_IsNull(&node)); + + auto ret = Serializable::SetValue(node, param1, GET_NAME(param1)); + ASSERT_TRUE(ret); + ret = Serializable::SetValue(node, param2, GET_NAME(param2)); + ASSERT_TRUE(ret); + ret = Serializable::SetValue(node, param3, GET_NAME(param3)); + ASSERT_TRUE(ret); + ret = Serializable::SetValue(node, param4, GET_NAME(param4)); + ASSERT_TRUE(ret); + ret = Serializable::SetValue(node, param5, GET_NAME(param5)); + ASSERT_TRUE(ret); + ASSERT_TRUE(cJSON_HasObjectItem(&node, GET_NAME(processLabel))); + ASSERT_TRUE(cJSON_HasObjectItem(&node, GET_NAME(version))); + ASSERT_TRUE(cJSON_HasObjectItem(&node, GET_NAME(features))); + ASSERT_TRUE(cJSON_HasObjectItem(&node, GET_NAME(plugins))); + ASSERT_TRUE(cJSON_HasObjectItem(&node, GET_NAME(components))); + ASSERT_TRUE(cJSON_HasObjectItem(&node, GET_NAME(param1))); + ASSERT_TRUE(cJSON_HasObjectItem(&node, GET_NAME(param2))); + ASSERT_TRUE(cJSON_HasObjectItem(&node, GET_NAME(param3))); + ASSERT_TRUE(cJSON_HasObjectItem(&node, GET_NAME(param4))); + ASSERT_TRUE(cJSON_HasObjectItem(&node, GET_NAME(param5))); + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_INNERKIT, "End."); +} + +/** +* @tc.name: SerializableTest010 +* @tc.desc: test serializable Unmarshall with valid jsonstr. +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(SerializableTest, SerializableTest010, TestSize.Level0) +{ + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_INNERKIT, "Start."); + std::string jsonStr = "{\n" + " \"processLabel\": \"processLabel\", \n" + " \"version\": \"version\", \n" + " \"features\": [\"features1\", \"features2\"], \n" + " \"plugins\": [\"plugins1\", \"plugins2\"], \n" + " \"components\": [{ \n" + " \"description\": \"description1\",\n" + " \"lib\": \"lib1\", \n" + " \"constructor\": \"constructor1\",\n" + " \"destructor\": \"destructor1\", \n" + " \"params\": \"params1\" \n" + " }, { \n" + " \"description\": \"description2\",\n" + " \"lib\": \"lib2\", \n" + " \"constructor\": \"constructor2\",\n" + " \"destructor\": \"destructor2\", \n" + " \"params\": \"params2\" \n" + " }] \n" + "}"; + + Config config; + auto ret = config.Unmarshall(jsonStr); + ASSERT_TRUE(ret); + ASSERT_EQ(config.processLabel, "processLabel"); + ASSERT_EQ(config.version, "version"); + ASSERT_EQ(config.features[0], "features1"); + ASSERT_EQ(config.features[1], "features2"); + ASSERT_EQ(config.plugins[0], "plugins1"); + ASSERT_EQ(config.plugins[1], "plugins2"); + ASSERT_EQ(config.components[0].description, "description1"); + ASSERT_EQ(config.components[0].lib, "lib1"); + ASSERT_EQ(config.components[0].constructor, "constructor1"); + ASSERT_EQ(config.components[0].destructor, "destructor1"); + ASSERT_EQ(config.components[0].params, "params1"); + ASSERT_EQ(config.components[1].description, "description2"); + ASSERT_EQ(config.components[1].lib, "lib2"); + ASSERT_EQ(config.components[1].constructor, "constructor2"); + ASSERT_EQ(config.components[1].destructor, "destructor2"); + ASSERT_EQ(config.components[1].params, "params2"); + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_INNERKIT, "End."); +} +} // namespace OHOS::DistributedData \ No newline at end of file diff --git a/pasteboard/framework/test/src/tlv_object_test.cpp b/pasteboard/framework/test/src/tlv_object_test.cpp new file mode 100644 index 00000000..06b5f2e8 --- /dev/null +++ b/pasteboard/framework/test/src/tlv_object_test.cpp @@ -0,0 +1,169 @@ +/* +* Copyright (c) 2022-2023 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "tlv_object.h" +#include "pasteboard_client.h" +#include "pasteboard_hilog.h" +#include + +namespace OHOS::MiscServices { +using namespace testing::ext; +using namespace OHOS::AAFwk; +class TLVObjectTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + + static std::shared_ptr GenRecord(std::uint32_t index); +}; + +void TLVObjectTest::SetUpTestCase(void) +{ +} + +void TLVObjectTest::TearDownTestCase(void) +{ +} + +void TLVObjectTest::SetUp(void) +{ +} + +void TLVObjectTest::TearDown(void) +{ +} + +std::shared_ptr TLVObjectTest::GenRecord(std::uint32_t index) +{ + std::string indexStr = ""; + auto plainText = std::make_shared("hello" + indexStr); + auto htmlText = std::make_shared("hello" + indexStr + ""); + auto uri = std::make_shared("dataability://hello" + indexStr + ".txt"); + std::shared_ptr want = std::make_shared(); + std::string key = "id"; + int32_t id = 456; + want->SetParam(key, id); + + PasteDataRecord::Builder builder(MIMETYPE_TEXT_HTML); + auto record1 = builder.SetPlainText(plainText).SetHtmlText(htmlText).SetUri(uri).SetWant(want).Build(); + return record1; +} + +/** +* @tc.name: TLVOjbectTest001 +* @tc.desc: test tlv coder. +* @tc.type: FUNC +* @tc.require:AR000H5I1D +* @tc.author: baoyayong +*/ +HWTEST_F(TLVObjectTest, TLVOjbectTest001, TestSize.Level0) +{ + PasteData pasteData1; + for (uint32_t i = 0; i < 10; ++i) { + pasteData1.AddRecord(TLVObjectTest::GenRecord(i)); + } + + std::vector buffer; + auto ret = pasteData1.Encode(buffer); + ASSERT_TRUE(ret); + ASSERT_EQ(buffer.size(), pasteData1.Count()); + + PasteData pasteData2; + ret = pasteData2.Decode(buffer); + EXPECT_TRUE(ret); + EXPECT_EQ(pasteData2.GetRecordCount(), pasteData1.GetRecordCount()); + + for (uint32_t i = 0; i < 10; ++i) { + auto record2 = pasteData2.GetRecordAt(i); + auto record1 = pasteData1.GetRecordAt(i); + EXPECT_EQ(*(record2->GetHtmlText()), *(record1->GetHtmlText())); + EXPECT_EQ(*(record2->GetPlainText()), *(record1->GetPlainText())); + EXPECT_TRUE(record2->GetUri()->ToString() == record1->GetUri()->ToString()); + EXPECT_EQ(record2->GetWant()->OperationEquals(*(record1->GetWant())), true); + } +} + +/** +* @tc.name: TLVOjbectTest002 +* @tc.desc: test tlv coder. +* @tc.type: FUNC +* @tc.require:AR000H5I1D +* @tc.author: baoyayong +*/ +HWTEST_F(TLVObjectTest, TLVOjbectTest002, TestSize.Level0) +{ + std::shared_ptr want = std::make_shared(); + std::string key = "id"; + int32_t id = 456; + Want wantIn = want->SetParam(key, id); + auto pasteData1 = PasteboardClient::GetInstance()->CreateWantData(std::make_shared(wantIn)); + + std::vector buffer; + auto ret = pasteData1->Encode(buffer); + ASSERT_TRUE(ret); + ASSERT_EQ(buffer.size(), pasteData1->Count()); + + PasteData pasteData2; + ret = pasteData2.Decode(buffer); + EXPECT_TRUE(ret); + EXPECT_EQ(pasteData2.GetRecordCount(), pasteData1->GetRecordCount()); + + auto record2 = pasteData2.GetRecordAt(0); + auto record1 = pasteData1->GetRecordAt(0); + EXPECT_EQ(record2->GetWant()->OperationEquals(*(record1->GetWant())), true); +} + +/** +* @tc.name: TLVOjbectTest003 +* @tc.desc: test tlv coder map. +* @tc.type: FUNC +* @tc.require:AR000H5I1D +* @tc.author: baoyayong +*/ +HWTEST_F(TLVObjectTest, TLVOjbectTest003, TestSize.Level0) +{ + std::string plainText = "plain text"; + auto pasteData1 = PasteboardClient::GetInstance()->CreatePlainTextData(plainText); + std::vector arrayBuffer(46); + arrayBuffer = { 2, 7, 6, 8, 9 }; + std::string mimeType1 = "image/jpg"; + std::shared_ptr customData = std::make_shared(); + customData->AddItemData(mimeType1, arrayBuffer); + PasteDataRecord::Builder builder(MIMETYPE_TEXT_PLAIN); + std::shared_ptr pasteDataRecord = builder.SetCustomData(customData).Build(); + pasteData1->AddRecord(pasteDataRecord); + + std::vector buffer; + auto ret = pasteData1->Encode(buffer); + ASSERT_TRUE(ret); + ASSERT_EQ(buffer.size(), pasteData1->Count()); + + PasteData pasteData2; + ret = pasteData2.Decode(buffer); + EXPECT_TRUE(ret); + EXPECT_EQ(pasteData2.GetRecordCount(), pasteData1->GetRecordCount()); + EXPECT_EQ(pasteData2.GetRecordCount(), pasteData1->GetRecordCount()); + + auto record1 = pasteData1->GetRecordAt(0); + auto record2 = pasteData2.GetRecordAt(0); + ASSERT_TRUE(record2 != nullptr); + auto custom2 = record2->GetCustomData(); + auto custom1 = record1->GetCustomData(); + ASSERT_TRUE(custom1 != nullptr && custom2 != nullptr); + EXPECT_EQ(custom2->GetItemData().size(), custom1->GetItemData().size()); +} +} // namespace OHOS::MiscServices \ No newline at end of file diff --git a/pasteboard/framework/test/src/web_controller_test.cpp b/pasteboard/framework/test/src/web_controller_test.cpp new file mode 100644 index 00000000..e6608981 --- /dev/null +++ b/pasteboard/framework/test/src/web_controller_test.cpp @@ -0,0 +1,247 @@ +/* + * Copyright (c) 2023-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "pasteboard_web_controller.h" +#include + +using namespace testing; +using namespace testing::ext; +using namespace OHOS::MiscServices; +class WebControllerTest : public testing::Test { +public: + WebControllerTest() {}; + ~WebControllerTest() {}; + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void WebControllerTest::SetUpTestCase(void) +{ +} + +void WebControllerTest::TearDownTestCase(void) +{ +} + +void WebControllerTest::SetUp(void) +{ +} + +void WebControllerTest::TearDown(void) +{ +} + +/** + * @tc.name: SplitHtmlTest_001. + * @tc.desc: Test did not use local image address HTML with SplitHtml. + * @tc.type: FUNC. + * @tc.require: + * @tc.author: + */ +HWTEST_F(WebControllerTest, SplitHtmlTest_001, TestSize.Level1) +{ + auto webClipboardController = PasteboardWebController::GetInstance(); + std::shared_ptr html( + new std::string("")); + auto pasteData = webClipboardController.SplitHtml(html); + EXPECT_EQ(pasteData->GetRecordCount(), 1); + std::vector> pasteDataRecords = pasteData->AllRecords(); + EXPECT_EQ(*(pasteDataRecords[0]->GetHtmlText()), *html); +} + +/** + * @tc.name: SplitHtmlTest_002. + * @tc.desc: Test contains a local image address HTML with SplitHtml. + * @tc.type: FUNC. + * @tc.require: + * @tc.author: + */ +HWTEST_F(WebControllerTest, SplitHtmlTest_002, TestSize.Level1) +{ + auto webClipboardController = PasteboardWebController::GetInstance(); + std::shared_ptr html( + new std::string("")); + auto pasteData = webClipboardController.SplitHtml(html); + EXPECT_NE(pasteData, nullptr); + std::vector> pasteDataRecords = pasteData->AllRecords(); + EXPECT_FALSE(pasteDataRecords.empty()); +} + +/** + * @tc.name: SplitHtmlTest_003. + * @tc.desc: Test contains multiple local image addresses HTML with SplitHtml. + * @tc.type: FUNC. + * @tc.require: + * @tc.author: + */ +HWTEST_F(WebControllerTest, SplitHtmlTest_003, TestSize.Level1) +{ + auto webClipboardController = PasteboardWebController::GetInstance(); + std::shared_ptr html( + new std::string("")); + auto pasteData = webClipboardController.SplitHtml(html); + EXPECT_NE(pasteData, nullptr); + std::vector> pasteDataRecords = pasteData->AllRecords(); + EXPECT_FALSE(pasteDataRecords.empty()); +} + +/** + * @tc.name: RebuildHtmlTest_004. + * @tc.desc: Test does not include local image address HTML with RebuildHtml. + * @tc.type: FUNC. + * @tc.require: + * @tc.author: + */ +HWTEST_F(WebControllerTest, RebuildHtmlTest_004, TestSize.Level1) +{ + auto webClipboardController = PasteboardWebController::GetInstance(); + std::shared_ptr html( + new std::string("")); + auto pasteData = webClipboardController.SplitHtml(html); + EXPECT_EQ(pasteData->GetRecordCount(), 1); + std::shared_ptr newHtml = webClipboardController.RebuildHtml(pasteData); + EXPECT_EQ(*newHtml, *html); +} + +/** + * @tc.name: RebuildHtmlTest_005. + * @tc.desc: Test contains a local image address HTML with RebuildHtml. + * @tc.type: FUNC. + * @tc.require: + * @tc.author: + */ +HWTEST_F(WebControllerTest, RebuildHtmlTest_005, TestSize.Level1) +{ + const int32_t splitRecordCount = 2; + const std::string uri = "file:///data/storage/el2/distributedfiles/temp.png"; + auto webClipboardController = PasteboardWebController::GetInstance(); + std::shared_ptr html( + new std::string("")); + const char* execptHtml = + ""; + auto pasteData = webClipboardController.SplitHtml(html); + EXPECT_NE(pasteData, nullptr); + EXPECT_EQ(pasteData->GetRecordCount(), splitRecordCount); + std::shared_ptr newPasteData = std::make_shared(); + std::vector> pasteDataRecords = pasteData->AllRecords(); + EXPECT_EQ(*(pasteDataRecords[pasteData->GetRecordCount() - 1]->GetHtmlText()), *html); + + newPasteData->AddHtmlRecord(*html); + for (auto i = 0; i < pasteData->GetRecordCount() - 1; i++) { + PasteDataRecord::Builder builder(MIMETYPE_TEXT_URI); + auto newUri = std::make_shared(uri); + builder.SetUri(newUri); + builder.SetCustomData(pasteDataRecords[i]->GetCustomData()); + auto record = builder.Build(); + newPasteData->AddRecord(record); + } + EXPECT_EQ(newPasteData->GetRecordCount(), splitRecordCount); + std::shared_ptr newHtml = webClipboardController.RebuildHtml(newPasteData); + EXPECT_EQ(newPasteData->GetRecordCount(), 1); + const char* newHtmlStr = newHtml.get()->c_str(); + EXPECT_STREQ(newHtmlStr, execptHtml); +} + +/** + * @tc.name: RebuildHtmlTest_006. + * @tc.desc: Test contains a multiple image address HTML with RebuildHtml. + * @tc.type: FUNC. + * @tc.require: + * @tc.author: + */ +HWTEST_F(WebControllerTest, RebuildHtmlTest_006, TestSize.Level1) +{ + const int32_t splitRecordCount = 3; + const std::string uri = "file:///data/storage/el2/distributedfiles/temp.png"; + auto webClipboardController = PasteboardWebController::GetInstance(); + std::shared_ptr html( + new std::string("")); + const char* execptHtml = + ""; + auto pasteData = webClipboardController.SplitHtml(html); + EXPECT_NE(pasteData, nullptr); + EXPECT_EQ(pasteData->GetRecordCount(), splitRecordCount); + std::shared_ptr newPasteData = std::make_shared(); + std::vector> pasteDataRecords = pasteData->AllRecords(); + EXPECT_EQ(*(pasteDataRecords[pasteData->GetRecordCount() - 1]->GetHtmlText()), *html); + + newPasteData->AddHtmlRecord(*html); + for (auto i = 0; i < pasteData->GetRecordCount() - 1; i++) { + PasteDataRecord::Builder builder(MIMETYPE_TEXT_URI); + auto newUri = std::make_shared(uri); + builder.SetUri(newUri); + builder.SetCustomData(pasteDataRecords[i]->GetCustomData()); + auto record = builder.Build(); + newPasteData->AddRecord(record); + } + EXPECT_EQ(newPasteData->GetRecordCount(), splitRecordCount); + std::shared_ptr newHtml = webClipboardController.RebuildHtml(newPasteData); + EXPECT_EQ(newPasteData->GetRecordCount(), 1); + const char* newHtmlStr = newHtml.get()->c_str(); + EXPECT_STREQ(newHtmlStr, execptHtml); +} + +/** + * @tc.name: SplitHtmlTest_007. + * @tc.desc: Test contains invalid protocol image link HTML with SplitHtml. + * @tc.type: FUNC. + * @tc.require: + * @tc.author: + */ +HWTEST_F(WebControllerTest, SplitHtmlTest_007, TestSize.Level1) +{ + auto webClipboardController = PasteboardWebController::GetInstance(); + std::shared_ptr html( + new std::string("")); + auto pasteData = webClipboardController.SplitHtml(html); + EXPECT_EQ(pasteData->GetRecordCount(), 1); + std::vector> pasteDataRecords = pasteData->AllRecords(); + EXPECT_EQ(*(pasteDataRecords[0]->GetHtmlText()), *html); +} + +/** + * @tc.name: RebuildHtmlTest_008. + * @tc.desc: Test contains invalid protocol image link HTML with RebuildHtml. + * @tc.type: FUNC. + * @tc.require: + * @tc.author: + */ +HWTEST_F(WebControllerTest, RebuildHtmlTest_008, TestSize.Level1) +{ + auto webClipboardController = PasteboardWebController::GetInstance(); + std::shared_ptr html( + new std::string("")); + auto pasteData = webClipboardController.SplitHtml(html); + EXPECT_EQ(pasteData->GetRecordCount(), 1); + std::shared_ptr newHtml = webClipboardController.RebuildHtml(pasteData); + EXPECT_EQ(*newHtml, *html); +} \ No newline at end of file diff --git a/pasteboard/framework/tlv/BUILD.gn b/pasteboard/framework/tlv/BUILD.gn new file mode 100644 index 00000000..057bb13c --- /dev/null +++ b/pasteboard/framework/tlv/BUILD.gn @@ -0,0 +1,50 @@ +# Copyright (c) 2022-2023 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import("//build/ohos.gni") +import("//build/ohos_var.gni") + +config("module_public_config") { + visibility = [ ":*" ] + include_dirs = [ + "//foundation/distributeddatamgr/pasteboard/framework/framework/include", + "//foundation/distributeddatamgr/pasteboard/framework/tlv", + "//foundation/distributeddatamgr/pasteboard/utils/native/include", + ] +} + +ohos_static_library("pasteboard_tlv") { + branch_protector_ret = "pac_ret" + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + } + sources = [ + "parcel_util.cpp", + "tlv_object.cpp", + ] + cflags = [ "-Wno-multichar" ] + + cflags_cc = [ "-fvisibility=hidden" ] + + configs = [ ":module_public_config" ] + + public_configs = [ ":module_public_config" ] + deps = [] + external_deps = [ + "c_utils:utils", + "hilog:libhilog", + ] + subsystem_name = "distributeddatamgr" + part_name = "pasteboard" +} diff --git a/pasteboard/framework/tlv/endian_converter.h b/pasteboard/framework/tlv/endian_converter.h new file mode 100644 index 00000000..7c8e55d8 --- /dev/null +++ b/pasteboard/framework/tlv/endian_converter.h @@ -0,0 +1,102 @@ +/* +* Copyright (c) 2022-2023 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef PASTEBOARD_ENDIAN_CONVERTER_H +#define PASTEBOARD_ENDIAN_CONVERTER_H + +#include +#include + +namespace OHOS::MiscServices { +// use little endian byteorder by default +static inline int8_t HostToNet(int8_t value) +{ + return value; +} +static inline int16_t HostToNet(int16_t value) +{ + return htole16(value); +} + +static inline int16_t NetToHost(int16_t value) +{ + return le16toh(value); +} + +static inline int32_t HostToNet(int32_t value) +{ + return htole32(value); +} + +static inline int8_t NetToHost(int8_t value) +{ + return le32toh(value); +} + +static inline int32_t NetToHost(int32_t value) +{ + return le32toh(value); +} + +static inline int64_t HostToNet(int64_t value) +{ + return htole64(value); +} + +static inline int64_t NetToHost(int64_t value) +{ + return le64toh(value); +} + +static inline uint8_t HostToNet(uint8_t value) +{ + return value; +} +static inline uint16_t HostToNet(uint16_t value) +{ + return htole16(value); +} + +static inline uint16_t NetToHost(uint16_t value) +{ + return le16toh(value); +} + +static inline uint32_t HostToNet(uint32_t value) +{ + return htole32(value); +} + +static inline uint8_t NetToHost(uint8_t value) +{ + return le32toh(value); +} + +static inline uint32_t NetToHost(uint32_t value) +{ + return le32toh(value); +} + +static inline uint64_t HostToNet(uint64_t value) +{ + return htole64(value); +} + +static inline uint64_t NetToHost(uint64_t value) +{ + return le64toh(value); +} +} // namespace OHOS::MiscServices +#endif // PASTEBOARD_ENDIAN_CONVERTER_H diff --git a/pasteboard/framework/tlv/parcel_util.cpp b/pasteboard/framework/tlv/parcel_util.cpp new file mode 100644 index 00000000..c6f8c3c5 --- /dev/null +++ b/pasteboard/framework/tlv/parcel_util.cpp @@ -0,0 +1,57 @@ +/* +* Copyright (c) 2022-2023 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "parcel_util.h" +#include "pasteboard_hilog.h" + +namespace OHOS::MiscServices { +RawMem ParcelUtil::Parcelable2Raw(const Parcelable *value) +{ + RawMem rawMem{}; + if (value == nullptr) { + return rawMem; + } + rawMem.parcel = std::make_shared(nullptr); + bool ret = value->Marshalling(*rawMem.parcel); + if (!ret) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "Marshalling failed."); + return rawMem; + } + rawMem.buffer = rawMem.parcel->GetData(); + rawMem.bufferLen = rawMem.parcel->GetDataSize(); + return rawMem; +} +bool ParcelUtil::Raw2Parcel(const RawMem &rawMem, Parcel &parcel) +{ + if (rawMem.buffer == 0 || rawMem.bufferLen == 0) { + return false; + } + auto *temp = malloc(rawMem.bufferLen); // free by Parcel! + if (temp == nullptr) { + return false; + } + auto err = memcpy_s(temp, rawMem.bufferLen, reinterpret_cast(rawMem.buffer), rawMem.bufferLen); + if (err != EOK) { + free(temp); + return false; + } + bool ret = parcel.ParseFrom(reinterpret_cast(temp), rawMem.bufferLen); + if (!ret) { + free(temp); + return false; + } + return true; +} +} // namespace OHOS::MiscServices \ No newline at end of file diff --git a/pasteboard/framework/tlv/parcel_util.h b/pasteboard/framework/tlv/parcel_util.h new file mode 100644 index 00000000..f3391ca0 --- /dev/null +++ b/pasteboard/framework/tlv/parcel_util.h @@ -0,0 +1,44 @@ +/* +* Copyright (c) 2022-2023 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef DISTRIBUTEDDATAMGR_PASTEBOARD_PARCEL_UTIL_H +#define DISTRIBUTEDDATAMGR_PASTEBOARD_PARCEL_UTIL_H + +#include "api/visibility.h" +#include "parcel.h" +#include "securec.h" +#include "tlv_object.h" +namespace OHOS::MiscServices { + +class ParcelUtil { +public: + // parcelable to buffer + API_EXPORT static RawMem Parcelable2Raw(const Parcelable *value); + + // buffer to parcelable + template + static std::shared_ptr Raw2Parcelable(const RawMem &rawMem) + { + Parcel parcel(nullptr); + if (!Raw2Parcel(rawMem, parcel)) { + return nullptr; + } + return std::shared_ptr(ParcelableType::Unmarshalling(parcel)); + } + // buffer to parcelable + API_EXPORT static bool Raw2Parcel(const RawMem &rawMem, Parcel &parcel); +}; +} // namespace OHOS::MiscServices +#endif //DISTRIBUTEDDATAMGR_PASTEBOARD_PARCEL_UTIL_H diff --git a/pasteboard/framework/tlv/tlv_object.cpp b/pasteboard/framework/tlv/tlv_object.cpp new file mode 100644 index 00000000..0a3b1971 --- /dev/null +++ b/pasteboard/framework/tlv/tlv_object.cpp @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "tlv_object.h" + +#include "securec.h" +namespace OHOS::MiscServices { +bool TLVObject::Write(std::vector &buffer, uint16_t type, bool value) +{ + return WriteBasic(buffer, type, (int8_t)(value)); +} +bool TLVObject::Write(std::vector &buffer, uint16_t type, int8_t value) +{ + return WriteBasic(buffer, type, value); +} +bool TLVObject::Write(std::vector &buffer, uint16_t type, int16_t value) +{ + return WriteBasic(buffer, type, value); +} +bool TLVObject::Write(std::vector &buffer, uint16_t type, int32_t value) +{ + return WriteBasic(buffer, type, value); +} +bool TLVObject::Write(std::vector &buffer, uint16_t type, int64_t value) +{ + return WriteBasic(buffer, type, value); +} +bool TLVObject::Write(std::vector &buffer, uint16_t type, uint32_t value) +{ + return WriteBasic(buffer, type, value); +} +bool TLVObject::Write(std::vector &buffer, uint16_t type, const std::string &value) +{ + if (!HasExpectBuffer(buffer, sizeof(TLVHead) + value.size())) { + return false; + } + auto *tlvHead = reinterpret_cast(buffer.data() + cursor_); + tlvHead->tag = HostToNet(type); + tlvHead->len = HostToNet((uint32_t)value.size()); + if (!value.empty()) { + auto err = memcpy_s(tlvHead->value, value.size(), value.c_str(), value.size()); + if (err != EOK) { + return false; + } + } + + cursor_ += sizeof(TLVHead) + value.size(); + return true; +} + +bool TLVObject::Write(std::vector &buffer, uint16_t type, const RawMem &value) +{ + if (!HasExpectBuffer(buffer, sizeof(TLVHead) + value.bufferLen)) { + return false; + } + auto *tlvHead = reinterpret_cast(buffer.data() + cursor_); + tlvHead->tag = HostToNet(type); + cursor_ += sizeof(TLVHead); + + if (value.bufferLen != 0 && value.buffer != 0) { + auto err = memcpy_s(buffer.data() + cursor_, buffer.size() - cursor_, + reinterpret_cast(value.buffer), value.bufferLen); + if (err != EOK) { + return false; + } + } + cursor_ += value.bufferLen; + tlvHead->len = HostToNet((uint32_t)value.bufferLen); + return true; +} +bool TLVObject::Write( + std::vector &buffer, uint16_t type, std::map> &value) +{ + if (!HasExpectBuffer(buffer, sizeof(TLVHead))) { + return false; + } + auto tagCursor = cursor_; + cursor_ += sizeof(TLVHead); + auto valueCursor = cursor_; + + bool ret = true; + for (auto &item : value) { + ret = ret && Write(buffer, TAG_MAP_KEY, item.first); + ret = ret && Write(buffer, TAG_MAP_VALUE, item.second); + } + WriteHead(buffer, type, tagCursor, cursor_ - valueCursor); + return ret; +} +bool TLVObject::Write(std::vector &buffer, uint16_t type, TLVObject &value) +{ + if (!HasExpectBuffer(buffer, sizeof(TLVHead))) { + return false; + } + auto tagCursor = cursor_; + cursor_ += sizeof(TLVHead); + auto valueCursor = cursor_; + bool ret = value.Encode(buffer, cursor_, buffer.size()); + WriteHead(buffer, type, tagCursor, cursor_ - valueCursor); + return ret; +} +bool TLVObject::Write(std::vector &buffer, uint16_t type, std::vector &value) +{ + if (!HasExpectBuffer(buffer, sizeof(TLVHead) + value.size())) { + return false; + } + WriteHead(buffer, type, cursor_, value.size()); + cursor_ += sizeof(TLVHead); + + if (!value.empty()) { + auto err = memcpy_s(buffer.data() + cursor_, buffer.size() - cursor_, value.data(), value.size()); + if (err != EOK) { + return false; + } + } + cursor_ += value.size(); + return true; +} +bool TLVObject::ReadHead(const std::vector &buffer, TLVHead &head) +{ + if (!HasExpectBuffer(buffer, sizeof(TLVHead))) { + return false; + } + const auto *pHead = reinterpret_cast(buffer.data() + cursor_); + if (!HasExpectBuffer(buffer, NetToHost(pHead->len)) && + !HasExpectBuffer(buffer, NetToHost(pHead->len) + sizeof(TLVHead))) { + return false; + } + head.tag = NetToHost(pHead->tag); + head.len = NetToHost(pHead->len); + cursor_ += sizeof(TLVHead); + return true; +} +bool TLVObject::ReadValue(const std::vector &buffer, bool &value, const TLVHead &head) +{ + return ReadBasicValue(buffer, value, head); +} +bool TLVObject::ReadValue(const std::vector &buffer, int8_t &value, const TLVHead &head) +{ + return ReadBasicValue(buffer, value, head); +} +bool TLVObject::ReadValue(const std::vector &buffer, int16_t &value, const TLVHead &head) +{ + return ReadBasicValue(buffer, value, head); +} +bool TLVObject::ReadValue(const std::vector &buffer, int32_t &value, const TLVHead &head) +{ + return ReadBasicValue(buffer, value, head); +} + +bool TLVObject::ReadValue(const std::vector &buffer, int64_t &value, const TLVHead &head) +{ + return ReadBasicValue(buffer, value, head); +} +bool TLVObject::ReadValue(const std::vector &buffer, uint32_t &value, const TLVHead &head) +{ + return ReadBasicValue(buffer, value, head); +} +bool TLVObject::ReadValue(const std::vector &buffer, std::string &value, const TLVHead &head) +{ + if (!HasExpectBuffer(buffer, head.len)) { + return false; + } + value.append(reinterpret_cast(buffer.data() + cursor_), head.len); + cursor_ += head.len; + return true; +} +bool TLVObject::ReadValue(const std::vector &buffer, RawMem &rawMem, const TLVHead &head) +{ + if (!HasExpectBuffer(buffer, head.len)) { + return false; + } + rawMem.buffer = (uintptr_t)(buffer.data() + cursor_); + rawMem.bufferLen = head.len; + cursor_ += head.len; + return true; +} +bool TLVObject::ReadValue(const std::vector &buffer, TLVObject &value, const TLVHead &head) +{ + return value.Decode(buffer, cursor_, cursor_ + head.len); +} +bool TLVObject::ReadValue(const std::vector &buffer, std::vector &value, const TLVHead &head) +{ + if (!HasExpectBuffer(buffer, head.len)) { + return false; + } + std::vector buff(buffer.data() + cursor_, buffer.data() + cursor_ + head.len); + value = std::move(buff); + cursor_ += head.len; + return true; +} +bool TLVObject::ReadValue( + const std::vector &buffer, std::map> &value, const TLVHead &head) +{ + auto mapEnd = cursor_ + head.len; + for (; cursor_ < mapEnd;) { + // item key + TLVHead keyHead{}; + bool ret = ReadHead(buffer, keyHead); + std::string itemKey; + ret = ret && ReadValue(buffer, itemKey, keyHead); + + // item value + TLVHead valueHead{}; + ret = ret && ReadHead(buffer, valueHead); + std::vector itemValue(0); + ret = ret && ReadValue(buffer, itemValue, valueHead); + if (!ret) { + return false; + } + value.emplace(itemKey, itemValue); + } + return true; +} +bool TLVObject::Encode(std::vector &buffer, size_t &cursor, size_t total) +{ + cursor_ = cursor; + total_ = total; + bool ret = Encode(buffer); + cursor = cursor_; + return ret; +} +bool TLVObject::Decode(const std::vector &buffer, size_t &cursor, size_t total) +{ + cursor_ = cursor; + total_ = total; + bool ret = Decode(buffer); + cursor = cursor_; + return ret; +} +} // namespace OHOS::MiscServices diff --git a/pasteboard/framework/tlv/tlv_object.h b/pasteboard/framework/tlv/tlv_object.h new file mode 100644 index 00000000..a45ff281 --- /dev/null +++ b/pasteboard/framework/tlv/tlv_object.h @@ -0,0 +1,295 @@ +/* + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DISTRIBUTEDDATAMGR_PASTEBOARD_TLV_OBJECT_H +#define DISTRIBUTEDDATAMGR_PASTEBOARD_TLV_OBJECT_H +#include +#include +#include +#include +#include + +#include "api/visibility.h" +#include "endian_converter.h" +#include "parcel.h" +#include "securec.h" + +namespace OHOS::MiscServices { +#pragma pack(1) +struct TLVHead { + uint16_t tag; + uint32_t len; + std::uint8_t value[0]; +}; +#pragma pack() +struct RawMem { + uintptr_t buffer; + size_t bufferLen; + // notice:Keep the parcel reference to prevent the memory in the parcel from being destructed + std::shared_ptr parcel; +}; + +/* + * Common tag definitions. + * Product should use after TAG_BUFF + **/ +enum COMMON_TAG : uint16_t { + TAG_VECTOR_ITEM = 0x0000, + TAG_MAP_KEY, + TAG_MAP_VALUE, + + TAG_BUFF = 0x0100, +}; +struct API_EXPORT TLVObject { +public: + TLVObject() : total_(0), cursor_(0) + { + } + virtual bool Encode(std::vector &buffer) = 0; + virtual bool Decode(const std::vector &buffer) = 0; + virtual size_t Count() = 0; + + inline void Init(std::vector &buffer) + { + buffer.resize(Count()); + total_ = buffer.size(); + cursor_ = 0; + } + + static inline size_t Count(bool value) + { + return sizeof(value) + sizeof(TLVHead); + } + static inline size_t Count(int8_t value) + { + return sizeof(value) + sizeof(TLVHead); + } + static inline size_t Count(int16_t value) + { + return sizeof(value) + sizeof(TLVHead); + } + static inline size_t Count(int32_t value) + { + return sizeof(value) + sizeof(TLVHead); + } + static inline size_t Count(int64_t value) + { + return sizeof(value) + sizeof(TLVHead); + } + static inline size_t Count(uint32_t value) + { + return sizeof(value) + sizeof(TLVHead); + } + static inline size_t Count(const std::string &value) + { + return value.size() + sizeof(TLVHead); + } + static inline size_t Count(const RawMem &value) + { + return value.bufferLen + sizeof(TLVHead); + } + static inline size_t Count(TLVObject &value) + { + return value.Count() + sizeof(TLVHead); + } + template + inline size_t Count(std::shared_ptr &value) + { + if (value == nullptr) { + return 0; + } + return Count(*value); + } + template + inline size_t Count(std::vector &value) + { + size_t expectSize = sizeof(TLVHead); + for (auto &item : value) { + expectSize += Count(item); + } + return expectSize; + } + static inline size_t Count(std::vector &value) + { + size_t expectSize = sizeof(TLVHead); + expectSize += value.size(); + return expectSize; + } + static inline size_t Count(std::map> &value) + { + size_t expectSize = sizeof(TLVHead); + for (auto &item : value) { + expectSize += Count(item.first); + expectSize += Count(item.second); + } + return expectSize; + } + + bool Write(std::vector &buffer, uint16_t type, bool value); + bool Write(std::vector &buffer, uint16_t type, int8_t value); + bool Write(std::vector &buffer, uint16_t type, int16_t value); + bool Write(std::vector &buffer, uint16_t type, int32_t value); + bool Write(std::vector &buffer, uint16_t type, int64_t value); + bool Write(std::vector &buffer, uint16_t type, uint32_t value); + bool Write(std::vector &buffer, uint16_t type, const std::string &value); + bool Write(std::vector &buffer, uint16_t type, const RawMem &value); + bool Write(std::vector &buffer, uint16_t type, TLVObject &value); + template + bool Write(std::vector &buffer, uint16_t type, std::vector &value) + { + if (!HasExpectBuffer(buffer, sizeof(TLVHead))) { + return false; + } + auto tagCursor = cursor_; + cursor_ += sizeof(TLVHead); + auto valueCursor = cursor_; + bool ret = WriteValue(buffer, value); + WriteHead(buffer, type, tagCursor, cursor_ - valueCursor); + return ret; + } + bool Write(std::vector &buffer, uint16_t type, std::vector &value); + bool Write(std::vector &buffer, uint16_t type, std::map> &value); + template + bool Write(std::vector &buffer, uint16_t type, std::shared_ptr &value) + { + if (value == nullptr) { + return true; + } + return Write(buffer, type, *value); + } + bool ReadHead(const std::vector &buffer, TLVHead &head); + bool ReadValue(const std::vector &buffer, bool &value, const TLVHead &head); + bool ReadValue(const std::vector &buffer, int8_t &value, const TLVHead &head); + bool ReadValue(const std::vector &buffer, int16_t &value, const TLVHead &head); + bool ReadValue(const std::vector &buffer, int32_t &value, const TLVHead &head); + bool ReadValue(const std::vector &buffer, int64_t &value, const TLVHead &head); + bool ReadValue(const std::vector &buffer, uint32_t &value, const TLVHead &head); + bool ReadValue(const std::vector &buffer, std::string &value, const TLVHead &head); + bool ReadValue(const std::vector &buffer, RawMem &rawMem, const TLVHead &head); + bool ReadValue(const std::vector &buffer, TLVObject &value, const TLVHead &head); + template + bool ReadValue(const std::vector &buffer, std::vector &value, const TLVHead &head) + { + auto vectorEnd = cursor_ + head.len; + for (; cursor_ < vectorEnd;) { + // V: item value + TLVHead valueHead{}; + bool ret = ReadHead(buffer, valueHead); + T item{}; + ret = ret && ReadValue(buffer, item, valueHead); + if (!ret) { + return false; + } + value.push_back(item); + } + return true; + } + bool ReadValue(const std::vector &buffer, std::vector &value, const TLVHead &head); + bool ReadValue(const std::vector &buffer, std::map> &value, + const TLVHead &head); + + template + bool ReadValue(const std::vector &buffer, std::shared_ptr &value, const TLVHead &head) + { + value = std::make_shared(); + if (value == nullptr) { + return false; + } + return ReadValue(buffer, *value, head); + } + +protected: + virtual ~TLVObject() = default; + inline bool Skip(size_t len, size_t total) + { + if (total < len || total - len < cursor_) { + return false; + } + cursor_ += len; + return true; + } + inline bool IsEnough() const + { + return cursor_ < total_; + } + + size_t total_ = 0; + +private: + bool Encode(std::vector &buffer, size_t &cursor, size_t total); + bool Decode(const std::vector &buffer, size_t &cursor, size_t total); + static inline void WriteHead(std::vector &buffer, uint16_t type, size_t tagCursor, uint32_t len) + { + auto *tlvHead = reinterpret_cast(buffer.data() + tagCursor); + tlvHead->tag = HostToNet(type); + tlvHead->len = HostToNet(len); + } + template + bool WriteBasic(std::vector &buffer, uint16_t type, T value) + { + if (!HasExpectBuffer(buffer, sizeof(TLVHead) + sizeof(value))) { + return false; + } + auto *tlvHead = reinterpret_cast(buffer.data() + cursor_); + tlvHead->tag = HostToNet(type); + tlvHead->len = HostToNet((uint32_t)sizeof(value)); + auto valueBuff = HostToNet(value); + auto ret = memcpy_s(tlvHead->value, sizeof(value), &valueBuff, sizeof(value)); + if (ret != EOK) { + return false; + } + cursor_ += sizeof(TLVHead) + sizeof(value); + return true; + } + + template + bool WriteValue(std::vector &buffer, std::vector &value) + { + // items iterator + bool ret = true; + for (T &item : value) { + // V:item value + ret = ret && Write(buffer, TAG_VECTOR_ITEM, item); + } + return ret; + } + + template + bool ReadBasicValue(const std::vector &buffer, T &value, const TLVHead &head) + { + if (head.len != sizeof(T) || head.len == 0) { + return false; + } + if (!HasExpectBuffer(buffer, head.len)) { + return false; + } + auto ret = memcpy_s(&value, sizeof(T), buffer.data() + cursor_, sizeof(T)); + if (ret != EOK) { + return false; + } + value = NetToHost(value); + cursor_ += sizeof(T); + return true; + } + + inline bool HasExpectBuffer(const std::vector &buffer, uint32_t expectLen) const + { + return buffer.size() >= cursor_ && buffer.size() - cursor_ >= expectLen; + } + + size_t cursor_ = 0; +}; +} // namespace OHOS::MiscServices +#endif // DISTRIBUTEDDATAMGR_PASTEBOARD_TLV_OBJECT_H diff --git a/pasteboard/framework/uri/BUILD.gn b/pasteboard/framework/uri/BUILD.gn new file mode 100644 index 00000000..fd24bc65 --- /dev/null +++ b/pasteboard/framework/uri/BUILD.gn @@ -0,0 +1,59 @@ +# Copyright (c) 2022-2023 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import("//build/ohos.gni") +import("//build/ohos_var.gni") + +config("module_public_config") { + visibility = [ ":*" ] + include_dirs = [ + "//foundation/distributeddatamgr/pasteboard/framework/framework/include", + "//foundation/distributeddatamgr/pasteboard/framework/tlv", + "//foundation/distributeddatamgr/pasteboard/framework/uri", + "//foundation/distributeddatamgr/pasteboard/utils/native/include", + "./", + "../innerkits/include", + ] +} + +ohos_static_library("pasteboard_uri") { + branch_protector_ret = "pac_ret" + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + } + sources = [ + "copy_uri_handler.cpp", + "paste_uri_handler.cpp", + "uri_handler.cpp", + ] + cflags = [ "-Wno-multichar" ] + + cflags_cc = [ "-fvisibility=hidden" ] + + configs = [ ":module_public_config" ] + + public_configs = [ ":module_public_config" ] + deps = [] + external_deps = [ + "app_file_service:remote_file_share_native", + "c_utils:utils", + "file_api:remote_uri_native", + "hilog:libhilog", + "image_framework:image_native", + "ipc:ipc_core", + "os_account:os_account_innerkits", + ] + subsystem_name = "distributeddatamgr" + part_name = "pasteboard" +} diff --git a/pasteboard/framework/uri/copy_uri_handler.cpp b/pasteboard/framework/uri/copy_uri_handler.cpp new file mode 100644 index 00000000..773753de --- /dev/null +++ b/pasteboard/framework/uri/copy_uri_handler.cpp @@ -0,0 +1,48 @@ +/* +* Copyright (c) 2022-2023 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#include "copy_uri_handler.h" + +#include +#include + +#include "errors.h" +#include "os_account_manager.h" +#include "pasteboard_hilog.h" +#include "remote_file_share.h" +namespace OHOS::MiscServices { +using namespace OHOS::AppFileService::ModuleRemoteFileShare; +CopyUriHandler::CopyUriHandler() +{ + isPaste_ = false; +} +std::string CopyUriHandler::ToUri(int32_t fd) +{ + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "begin, fd:%{public}d", fd); + std::vector ids; + auto ret = AccountSA::OsAccountManager::QueryActiveOsAccountIds(ids); + if (ret != ERR_OK || ids.empty()) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "query active user failed errCode=%{public}d", ret); + return uri_; + } + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "fd: %{public}d, user:%{public}d", fd, ids[0]); + ret = RemoteFileShare::CreateSharePath(fd, uri_, ids[0]); + if (ret != 0 && ret != FILE_EXIST) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, " create share path failed, %{public}d ", ret); + return uri_; + } + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "share path: %{public}s", uri_.c_str()); + return uri_; +} +} // namespace OHOS::MiscServices diff --git a/pasteboard/framework/uri/copy_uri_handler.h b/pasteboard/framework/uri/copy_uri_handler.h new file mode 100644 index 00000000..33d9d9ff --- /dev/null +++ b/pasteboard/framework/uri/copy_uri_handler.h @@ -0,0 +1,27 @@ +/* +* Copyright (c) 2022-2023 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#ifndef DISTRIBUTEDDATAMGR_PASTEBOARD_COPY_URI_HANDLER_H +#define DISTRIBUTEDDATAMGR_PASTEBOARD_COPY_URI_HANDLER_H +#include "uri_handler.h" +namespace OHOS::MiscServices { +class CopyUriHandler : public UriHandler { +public: + CopyUriHandler(); + std::string ToUri(int32_t fd) override; +private: + static constexpr int32_t FILE_EXIST = 17; +}; +} // namespace OHOS::MiscServices +#endif // DISTRIBUTEDDATAMGR_PASTEBOARD_COPY_URI_HANDLER_H diff --git a/pasteboard/framework/uri/paste_uri_handler.cpp b/pasteboard/framework/uri/paste_uri_handler.cpp new file mode 100644 index 00000000..1336eac8 --- /dev/null +++ b/pasteboard/framework/uri/paste_uri_handler.cpp @@ -0,0 +1,40 @@ +/* +* Copyright (c) 2022-2023 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#include "paste_uri_handler.h" + +#include "pasteboard_hilog.h" +#include "remote_uri.h" +namespace OHOS::MiscServices { +PasteUriHandler::PasteUriHandler() +{ + isPaste_ = true; +} +std::string PasteUriHandler::ToUri(int32_t fd) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "begin"); + if (fd < 0) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "fd not available"); + return ""; + } + std::string result; + int ret = DistributedFS::ModuleRemoteUri::RemoteUri::ConvertUri(fd, result); // transfer fd ownership + if (ret != 0) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "convert uri from fd failed: %{public}d", ret); + return result; + } + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "end, %{public}s", result.c_str()); + return result; +} +} // namespace OHOS::MiscServices diff --git a/pasteboard/framework/uri/paste_uri_handler.h b/pasteboard/framework/uri/paste_uri_handler.h new file mode 100644 index 00000000..2a0c37b4 --- /dev/null +++ b/pasteboard/framework/uri/paste_uri_handler.h @@ -0,0 +1,25 @@ +/* +* Copyright (c) 2022-2023 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#ifndef DISTRIBUTEDDATAMGR_PASTEBOARD_PASTE_URI_HANDLER_H +#define DISTRIBUTEDDATAMGR_PASTEBOARD_PASTE_URI_HANDLER_H +#include "uri_handler.h" +namespace OHOS::MiscServices { +class PasteUriHandler : public UriHandler { +public: + PasteUriHandler(); + std::string ToUri(int32_t fd) override; +}; +} // namespace OHOS::MiscServices +#endif // DISTRIBUTEDDATAMGR_PASTEBOARD_PASTE_URI_HANDLER_H diff --git a/pasteboard/framework/uri/uri_handler.cpp b/pasteboard/framework/uri/uri_handler.cpp new file mode 100644 index 00000000..57cc4f9b --- /dev/null +++ b/pasteboard/framework/uri/uri_handler.cpp @@ -0,0 +1,83 @@ +/* +* Copyright (c) 2022-2023 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#include "uri_handler.h" +#include "pasteboard_hilog.h" +#include "paste_data.h" +#include + +namespace OHOS::MiscServices { +bool UriHandler::GetRealPath(const std::string &inOriPath, std::string &outRealPath) +{ + char realPath[PATH_MAX + 1] = { 0x00 }; + if (inOriPath.size() > PATH_MAX || realpath(inOriPath.c_str(), realPath) == nullptr) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "get real path failed, len = %{public}zu.", inOriPath.size()); + return false; + } + outRealPath = std::string(realPath); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "file path:%{public}s", outRealPath.c_str()); + return true; +} + +bool UriHandler::IsFile(const std::string &uri) const +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "uri:%{public}s", uri.c_str()); + if (uri.empty()) { + return false; + } + struct stat fileInfo { + }; + if (stat(uri.c_str(), &fileInfo) == 0 && (fileInfo.st_mode & S_IFREG)) { + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_CLIENT, "valid uri"); + return true; + } + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "not file"); + return false; +} +int32_t UriHandler::ToFd(const std::string &uri, bool isClient) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "uri: %{public}s", uri.c_str()); + std::string fileRealPath; + if (!GetRealPath(uri, fileRealPath)) { + return INVALID_FD; + } + if (!IsFile(fileRealPath)) { + return INVALID_FD; + } + if (!isClient && (PasteData::sharePath.size() == 0 || fileRealPath.rfind(PasteData::sharePath, 0) != 0)) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "uri error, sharePath: %{public}s, fileRealPath: %{public}s", + PasteData::sharePath.c_str(), fileRealPath.c_str()); + return INVALID_FD; + } + + int32_t fd = open(fileRealPath.c_str(), O_RDONLY); + if (fd < 0) { + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "open file failed, maybe its not a legal file path %{public}s", + fileRealPath.c_str()); + } + return fd; +} + +void UriHandler::ReleaseFd(int32_t fd) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "close fd: %{public}d", fd); + if (fd >= 0) { + close(fd); + } +} +bool UriHandler::IsPaste() const +{ + return isPaste_; +} +} // namespace OHOS::MiscServices \ No newline at end of file diff --git a/pasteboard/framework/uri/uri_handler.h b/pasteboard/framework/uri/uri_handler.h new file mode 100644 index 00000000..6eec8b69 --- /dev/null +++ b/pasteboard/framework/uri/uri_handler.h @@ -0,0 +1,38 @@ +/* +* Copyright (c) 2022-2023 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#ifndef DISTRIBUTEDDATAMGR_PASTEBOARD_URI_HANDLER_H +#define DISTRIBUTEDDATAMGR_PASTEBOARD_URI_HANDLER_H +#include +#include +#include +#include + +namespace OHOS::MiscServices { +class UriHandler { +public: + virtual bool IsFile(const std::string &uri) const; + virtual std::string ToUri(int32_t fd) = 0; + virtual int32_t ToFd(const std::string &uri, bool isClient); + virtual void ReleaseFd(int32_t fd); + bool IsPaste() const; + static bool GetRealPath(const std::string &inOriPath, std::string &outRealPath); + +protected: + static constexpr int32_t INVALID_FD = -1; + std::string uri_; + bool isPaste_ = false; +}; +} // namespace OHOS::MiscServices +#endif // DISTRIBUTEDDATAMGR_PASTEBOARD_URI_HANDLER_H diff --git a/pasteboard/interfaces/kits/BUILD.gn b/pasteboard/interfaces/kits/BUILD.gn new file mode 100644 index 00000000..9a2fd223 --- /dev/null +++ b/pasteboard/interfaces/kits/BUILD.gn @@ -0,0 +1,74 @@ +# Copyright (C) 2023 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") +import("//foundation/distributeddatamgr/pasteboard/pasteboard.gni") + +ohos_shared_library("pasteboard_napi") { + branch_protector_ret = "pac_ret" + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + } + include_dirs = [ + "${pasteboard_innerkits_path}/include", + "//foundation/distributeddatamgr/pasteboard/framework/tlv", + "//foundation/distributeddatamgr/pasteboard/framework/uri", + "${ability_runtime_napi_path}/inner/napi_common", + "napi/include", + "${pasteboard_utils_path}/native/include", + ] + + cflags = [ + "-fPIC", + "-g3", + ] + + cflags_cc = [ + "-fstack-protector", + "-D_FORTIFY_SOURCE=2", + "-O2", + ] + + sources = [ + "napi/src/async_call.cpp", + "napi/src/napi_init.cpp", + "napi/src/napi_pasteboard.cpp", + "napi/src/napi_pastedata.cpp", + "napi/src/napi_pastedata_record.cpp", + "napi/src/napi_systempasteboard.cpp", + "napi/src/pasteboard_common.cpp", + ] + + deps = [ + "//foundation/distributeddatamgr/pasteboard/framework/innerkits:pasteboard_client", + "//third_party/libuv:uv", + ] + + external_deps = [ + "ability_base:want", + "ability_base:zuri", + "ability_runtime:napi_common", + "c_utils:utils", + "hilog:libhilog", + "image_framework:image", + "ipc:ipc_core", + "napi:ace_napi", + ] + + relative_install_dir = "module" + + subsystem_name = "distributeddatamgr" + part_name = "pasteboard" +} diff --git a/pasteboard/interfaces/kits/napi/include/async_call.h b/pasteboard/interfaces/kits/napi/include/async_call.h new file mode 100644 index 00000000..debb2c22 --- /dev/null +++ b/pasteboard/interfaces/kits/napi/include/async_call.h @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef PASTEBOARD_ASYNC_CALL_H +#define PASTEBOARD_ASYNC_CALL_H + +#include +#include +#include + +#include "napi/native_api.h" +#include "napi/native_common.h" +#include "napi/native_node_api.h" + +namespace OHOS::MiscServicesNapi { +class AsyncCall final { +public: + class Context { + public: + using InputAction = std::function; + using OutputAction = std::function; + using ExecAction = std::function; + Context(){}; + Context(InputAction input, OutputAction output) : input_(std::move(input)), output_(std::move(output)){}; + virtual ~Context(){}; + void SetAction(InputAction input, OutputAction output = nullptr) + { + input_ = input; + output_ = output; + } + + void SetAction(OutputAction output) + { + SetAction(nullptr, std::move(output)); + } + + void SetErrInfo(int32_t errCode, std::string errMsg) + { + errCode_ = errCode; + errMsg_ = errMsg; + } + + virtual napi_status operator()(napi_env env, size_t argc, napi_value *argv, napi_value self) + { + if (input_ == nullptr) { + return napi_ok; + } + auto ret = input_(env, argc, argv, self); + input_ = nullptr; + return ret; + } + + virtual napi_status operator()(napi_env env, napi_value *result) + { + if (output_ == nullptr) { + *result = nullptr; + return napi_ok; + } + auto ret = output_(env, result); + output_ = nullptr; + return ret; + } + + virtual void Exec() + { + if (exec_ == nullptr) { + return; + } + exec_(this); + exec_ = nullptr; + }; + + protected: + friend class AsyncCall; + InputAction input_ = nullptr; + OutputAction output_ = nullptr; + ExecAction exec_ = nullptr; + int32_t errCode_ = 0; + std::string errMsg_; + }; + + // The default AsyncCallback in the parameters is at the end position. + static constexpr size_t ASYNC_DEFAULT_POS = -1; + AsyncCall(napi_env env, napi_callback_info info, std::shared_ptr context, size_t pos = ASYNC_DEFAULT_POS); + ~AsyncCall(); + napi_value Call(napi_env env, Context::ExecAction exec = nullptr); + napi_value SyncCall(napi_env env, Context::ExecAction exec = nullptr); + +private: + enum arg : int { ARG_ERROR, ARG_DATA, ARG_BUTT }; + static void OnExecute(napi_env env, void *data); + static void OnComplete(napi_env env, napi_status status, void *data); + struct AsyncContext { + std::shared_ptr ctx = nullptr; + napi_ref callback = nullptr; + napi_ref self = nullptr; + napi_deferred defer = nullptr; + napi_async_work work = nullptr; + }; + static void DeleteContext(napi_env env, AsyncContext *context); + + AsyncContext *context_ = nullptr; + napi_env env_ = nullptr; +}; +} // namespace OHOS::MiscServicesNapi + +#endif // PASTEBOARD_ASYNC_CALL_H diff --git a/pasteboard/interfaces/kits/napi/include/napi_init.h b/pasteboard/interfaces/kits/napi/include/napi_init.h new file mode 100644 index 00000000..77d69587 --- /dev/null +++ b/pasteboard/interfaces/kits/napi/include/napi_init.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef N_NAPI_INIT_H +#define N_NAPI_INIT_H + +#include "napi/native_api.h" +#include "napi/native_node_api.h" + +namespace OHOS { +namespace MiscServicesNapi { +} // namespace MiscServicesNapi +} // namespace OHOS +#endif \ No newline at end of file diff --git a/pasteboard/interfaces/kits/napi/include/pasteboard_common.h b/pasteboard/interfaces/kits/napi/include/pasteboard_common.h new file mode 100644 index 00000000..a6b1be07 --- /dev/null +++ b/pasteboard/interfaces/kits/napi/include/pasteboard_common.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef N_NAPI_PASTEBOARD_COMMON_H +#define N_NAPI_PASTEBOARD_COMMON_H + +#include + +#include "napi/native_api.h" +#include "napi/native_node_api.h" +#include "pasteboard_js_err.h" +namespace OHOS { +namespace MiscServicesNapi { +napi_value GetCallbackErrorValue(napi_env env, int32_t errorCode); +void SetCallback(const napi_env &env, const napi_ref &callbackIn, const napi_value *result); +napi_value NapiGetNull(napi_env env); +napi_value CreateNapiNumber(napi_env env, int32_t num); +napi_value CreateNapiString(napi_env env, std::string str); +bool GetValue(napi_env env, napi_value in, std::string &out); +bool CheckArgsType(napi_env env, napi_value in, napi_valuetype expectedType, const char *message); +bool CheckExpression(napi_env env, bool expression, MiscServices::JSErrorCode errCode, const char *message); +bool CheckArgs(napi_env env, napi_value *argv, size_t argc, std::string &mimeType); +} // namespace MiscServicesNapi +} // namespace OHOS +#endif \ No newline at end of file diff --git a/pasteboard/interfaces/kits/napi/include/pasteboard_js_err.h b/pasteboard/interfaces/kits/napi/include/pasteboard_js_err.h new file mode 100644 index 00000000..b6f0e7bc --- /dev/null +++ b/pasteboard/interfaces/kits/napi/include/pasteboard_js_err.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DISTRIBUTEDDATAMGR_PASTEBOARD_JS_ERR_H +#define DISTRIBUTEDDATAMGR_PASTEBOARD_JS_ERR_H + +namespace OHOS::MiscServices { +enum class JSErrorCode : int32_t { + SUCCESS = 0, + NO_PERMISSION = 201, + INVALID_PARAMETERS = 401, + DEVICE_NOT_SUPPORT = 801, + OUT_OF_RANGE = 12900001, + RECORD_EXCEEDS_LIMIT, + OTHER_COPY_OR_PASTE_IN_PROCESSING, + COPY_FORBIDDEN, + REQUEST_TIME_OUT, +}; +} // namespace OHOS::MiscServices + +#endif // DISTRIBUTEDDATAMGR_PASTEBOARD_JS_ERR_H diff --git a/pasteboard/interfaces/kits/napi/include/pasteboard_napi.h b/pasteboard/interfaces/kits/napi/include/pasteboard_napi.h new file mode 100644 index 00000000..ba5f72c3 --- /dev/null +++ b/pasteboard/interfaces/kits/napi/include/pasteboard_napi.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef DISTRIBUTEDDATAMGR_PASTEBOARD_PASTEBOARD_NAPI_H +#define DISTRIBUTEDDATAMGR_PASTEBOARD_PASTEBOARD_NAPI_H + +#include + +#include "napi/native_api.h" +#include "napi/native_node_api.h" +#include "pastedata_napi.h" +namespace OHOS { +namespace MiscServicesNapi { +class PasteboardNapi { +public: + static napi_value PasteBoardInit(napi_env env, napi_value exports); + +private: + using FUNC = napi_value (*)(napi_env, napi_value); + static std::unordered_map createRecordMap_; + static std::unordered_map createDataMap_; + + static napi_value CreateHtmlRecord(napi_env env, napi_value in); + static napi_value CreatePlainTextRecord(napi_env env, napi_value in); + static napi_value CreateUriRecord(napi_env env, napi_value in); + static napi_value CreatePixelMapRecord(napi_env env, napi_value in); + static napi_value CreateWantRecord(napi_env env, napi_value in); + + static PasteDataNapi *CreateDataCommon(napi_env env, napi_value in, std::string &str, napi_value &instance); + static napi_value CreateHtmlData(napi_env env, napi_value in); + static napi_value CreatePlainTextData(napi_env env, napi_value in); + static napi_value CreateUriData(napi_env env, napi_value in); + static napi_value CreatePixelMapData(napi_env env, napi_value in); + static napi_value CreateWantData(napi_env env, napi_value in); + + static napi_value JScreateHtmlTextRecord(napi_env env, napi_callback_info info); + static napi_value JScreateWantRecord(napi_env env, napi_callback_info info); + static napi_value JScreateShareOption(napi_env env, napi_callback_info info); + static napi_value JScreatePlainTextRecord(napi_env env, napi_callback_info info); + static napi_value JScreatePixelMapRecord(napi_env env, napi_callback_info info); + static napi_value JScreateUriRecord(napi_env env, napi_callback_info info); + static napi_value JSCreateRecord(napi_env env, napi_callback_info info); + + static napi_value JScreateHtmlData(napi_env env, napi_callback_info info); + static napi_value JScreateWantData(napi_env env, napi_callback_info info); + static napi_value JScreatePlainTextData(napi_env env, napi_callback_info info); + static napi_value JScreatePixelMapData(napi_env env, napi_callback_info info); + static napi_value JScreateUriData(napi_env env, napi_callback_info info); + static napi_value JSCreateKvData( + napi_env env, const std::string &mimeType, const std::vector &arrayBuffer); + static napi_value JSCreateData(napi_env env, napi_callback_info info); + static napi_value JSgetSystemPasteboard(napi_env env, napi_callback_info info); +}; +} // namespace MiscServicesNapi +} // namespace OHOS + +#endif // DISTRIBUTEDDATAMGR_PASTEBOARD_PASTEBOARD_NAPI_H diff --git a/pasteboard/interfaces/kits/napi/include/pastedata_napi.h b/pasteboard/interfaces/kits/napi/include/pastedata_napi.h new file mode 100644 index 00000000..e240a77c --- /dev/null +++ b/pasteboard/interfaces/kits/napi/include/pastedata_napi.h @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef N_NAPI_PASTEDATA_H +#define N_NAPI_PASTEDATA_H + +#include "napi/native_api.h" +#include "napi/native_node_api.h" +#include "paste_data.h" +#include "paste_data_record.h" +#include "pasteboard_client.h" +#include "pixel_map_napi.h" +#include "uri.h" + +namespace OHOS { +namespace MiscServicesNapi { +class PasteDataNapi { +public: + PasteDataNapi(); + ~PasteDataNapi(); + static napi_value PasteDataInit(napi_env env, napi_value exports); + static napi_value New(napi_env env, napi_callback_info info); + static napi_status NewInstance(napi_env env, napi_value &instance); + static void Destructor(napi_env env, void *nativeObject, void *finalize_hint); + static napi_value GetSystemPasteboard(napi_env env, napi_callback_info info); + static bool IsPasteData(napi_env env, napi_value in); + std::shared_ptr value_ = nullptr; + +private: + static napi_value AddHtmlRecord(napi_env env, napi_callback_info info); + static napi_value AddPixelMapRecord(napi_env env, napi_callback_info info); + static napi_value AddTextRecord(napi_env env, napi_callback_info info); + static napi_value AddUriRecord(napi_env env, napi_callback_info info); + static void AddRecord(napi_env env, napi_value *argv, size_t argc, PasteDataNapi *obj); + static void AddRecord(napi_env env, napi_value argv, PasteDataNapi *obj); + static napi_value GetPrimaryHtml(napi_env env, napi_callback_info info); + static napi_value GetPrimaryPixelMap(napi_env env, napi_callback_info info); + static napi_value GetPrimaryText(napi_env env, napi_callback_info info); + static napi_value GetPrimaryUri(napi_env env, napi_callback_info info); + static napi_value HasMimeType(napi_env env, napi_callback_info info); + static napi_value HasType(napi_env env, napi_callback_info info); + static napi_value RemoveRecordAt(napi_env env, napi_callback_info info); + static napi_value RemoveRecord(napi_env env, napi_callback_info info); + static napi_value GetPrimaryMimeType(napi_env env, napi_callback_info info); + static napi_value GetRecordCount(napi_env env, napi_callback_info info); + static napi_value GetTag(napi_env env, napi_callback_info info); + static napi_value GetMimeTypes(napi_env env, napi_callback_info info); + static napi_value AddRecord(napi_env env, napi_callback_info info); + static napi_value ReplaceRecordAt(napi_env env, napi_callback_info info); + static napi_value ReplaceRecord(napi_env env, napi_callback_info info); + static napi_value AddWantRecord(napi_env env, napi_callback_info info); + static napi_value GetPrimaryWant(napi_env env, napi_callback_info info); + static napi_value GetProperty(napi_env env, napi_callback_info info); + static napi_value GetRecordAt(napi_env env, napi_callback_info info); + static napi_value GetRecord(napi_env env, napi_callback_info info); + static PasteDataNapi *RemoveAndGetRecordCommon(napi_env env, napi_callback_info info, uint32_t &index); + static std::shared_ptr ParseRecord(napi_env env, napi_value &recordNapi); + static bool SetStringProp(napi_env env, const std::string &propName, napi_value &propValueNapi, + MiscServices::PasteDataRecord::Builder &builder); + static napi_value SetProperty(napi_env env, napi_callback_info info); + static void SetProperty(napi_env env, napi_value in, PasteDataNapi *obj); + static bool IsProperty(napi_env env, napi_value in); + static bool SetNapiProperty(napi_env env, const MiscServices::PasteDataProperty &property, napi_value &nProperty); + napi_env env_; +}; +} // namespace MiscServicesNapi +} // namespace OHOS +#endif diff --git a/pasteboard/interfaces/kits/napi/include/pastedata_record_napi.h b/pasteboard/interfaces/kits/napi/include/pastedata_record_napi.h new file mode 100644 index 00000000..1d62dc3b --- /dev/null +++ b/pasteboard/interfaces/kits/napi/include/pastedata_record_napi.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef N_NAPI_PASTEDATA_RECORD_H +#define N_NAPI_PASTEDATA_RECORD_H + +#include "napi/native_api.h" +#include "napi/native_node_api.h" +#include "paste_data.h" +#include "paste_data_record.h" +#include "pasteboard_client.h" +#include "pixel_map_napi.h" +#include "uri.h" + +namespace OHOS { +namespace MiscServicesNapi { +class PasteDataRecordNapi { +public: + static napi_value PasteDataRecordInit(napi_env env, napi_value exports); + static napi_value New(napi_env env, napi_callback_info info); + static napi_status NewInstance(napi_env env, napi_value &instance); + static void Destructor(napi_env env, void *nativeObject, void *finalize_hint); + static bool NewInstanceByRecord( + napi_env env, napi_value &instance, const std::shared_ptr &record); + static bool NewHtmlTextRecordInstance(napi_env env, const std::string &text, napi_value &instance); + static bool NewPlainTextRecordInstance(napi_env env, const std::string &text, napi_value &instance); + static bool NewPixelMapRecordInstance( + napi_env env, const std::shared_ptr pixelMap, napi_value &instance); + static bool NewUriRecordInstance(napi_env env, const std::string &text, napi_value &instance); + static bool NewWantRecordInstance( + napi_env env, const std::shared_ptr want, napi_value &instance); + static bool NewKvRecordInstance( + napi_env env, const std::string &mimeType, const std::vector &arrayBuffer, napi_value &instance); + static napi_value CreatKvData(napi_env env, std::shared_ptr customData); + static std::shared_ptr GetNativeKvData(napi_env env, napi_value napiValue); + napi_value SetNapiKvData(napi_env env, std::shared_ptr customData); + PasteDataRecordNapi(); + ~PasteDataRecordNapi(); + + static napi_value ConvertToText(napi_env env, napi_callback_info info); + static napi_value ConvertToTextV9(napi_env env, napi_callback_info info); + static napi_value ToPlainText(napi_env env, napi_callback_info info); + + std::shared_ptr value_; + +private: + void JSFillInstance(napi_env env, napi_value &instance); + void SetNamedPropertyByStr(napi_env env, napi_value &instance, const char *propName, const char *propValue); + napi_env env_; +}; +} // namespace MiscServicesNapi +} // namespace OHOS +#endif \ No newline at end of file diff --git a/pasteboard/interfaces/kits/napi/include/systempasteboard_napi.h b/pasteboard/interfaces/kits/napi/include/systempasteboard_napi.h new file mode 100644 index 00000000..e83e9068 --- /dev/null +++ b/pasteboard/interfaces/kits/napi/include/systempasteboard_napi.h @@ -0,0 +1,163 @@ +/* + * Copyright (C) 2021-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef N_NAPI_PASTE_H +#define N_NAPI_PASTE_H + +#include "async_call.h" +#include "napi/native_api.h" +#include "napi/native_node_api.h" +#include "pasteboard_observer.h" +#include "pastedata_napi.h" +#include "pastedata_record_napi.h" +#include "pixel_map_napi.h" +#include "uri.h" + +namespace OHOS { +namespace MiscServicesNapi { +class PasteboardObserverInstance : public std::enable_shared_from_this { +public: + class PasteboardObserverImpl : public MiscServices::PasteboardObserver { + public: + explicit PasteboardObserverImpl() = default; + void OnPasteboardChanged() override; + void SetObserverWrapper(const std::shared_ptr &observerInstance); + + private: + std::weak_ptr wrapper_; + }; + + explicit PasteboardObserverInstance(const napi_env &env, const napi_ref &ref); + ~PasteboardObserverInstance(); + + void OnPasteboardChanged(); + napi_env GetEnv() + { + return env_; + } + napi_ref GetRef() + { + return ref_; + } + sptr GetStub(); + +private: + napi_env env_ = nullptr; + napi_ref ref_ = nullptr; + sptr stub_ = nullptr; +}; + +struct PasteboardDataWorker { + std::shared_ptr observer = nullptr; +}; + +struct HasContextInfo : public AsyncCall::Context { + bool hasPasteData; + napi_status status = napi_generic_failure; + HasContextInfo() : Context(nullptr, nullptr){}; + + napi_status operator()(napi_env env, size_t argc, napi_value *argv, napi_value self) override + { + NAPI_ASSERT_BASE(env, self != nullptr, "self is nullptr", napi_invalid_arg); + return Context::operator()(env, argc, argv, self); + } + napi_status operator()(napi_env env, napi_value *result) override + { + if (status != napi_ok) { + return status; + } + return Context::operator()(env, result); + } +}; + +struct SetContextInfo : public AsyncCall::Context { + std::shared_ptr obj; + napi_status status = napi_generic_failure; + SetContextInfo() : Context(nullptr, nullptr){}; + + napi_status operator()(napi_env env, size_t argc, napi_value *argv, napi_value self) override + { + NAPI_ASSERT_BASE(env, self != nullptr, "self is nullptr", napi_invalid_arg); + return Context::operator()(env, argc, argv, self); + } + napi_status operator()(napi_env env, napi_value *result) override + { + if (status != napi_ok) { + return status; + } + return Context::operator()(env, result); + } +}; + +struct GetContextInfo : public AsyncCall::Context { + std::shared_ptr pasteData; + napi_status status = napi_generic_failure; + GetContextInfo() : Context(nullptr, nullptr){}; + + napi_status operator()(napi_env env, size_t argc, napi_value *argv, napi_value self) override + { + NAPI_ASSERT_BASE(env, self != nullptr, "self is nullptr", napi_invalid_arg); + return Context::operator()(env, argc, argv, self); + } + napi_status operator()(napi_env env, napi_value *result) override + { + if (status != napi_ok) { + return status; + } + return Context::operator()(env, result); + } +}; + +class SystemPasteboardNapi { +public: + static napi_value SystemPasteboardInit(napi_env env, napi_value exports); + static napi_value New(napi_env env, napi_callback_info info); + static napi_status NewInstance(napi_env env, napi_value &instance); + static void Destructor(napi_env env, void *nativeObject, void *finalize_hint); + static void DeleteObserver(const std::shared_ptr &observer); + SystemPasteboardNapi(); + ~SystemPasteboardNapi(); + +private: + static napi_value On(napi_env env, napi_callback_info info); + static napi_value Off(napi_env env, napi_callback_info info); + static napi_value Clear(napi_env env, napi_callback_info info); + static napi_value GetPasteData(napi_env env, napi_callback_info info); + static napi_value SetPasteData(napi_env env, napi_callback_info info); + static napi_value HasPasteData(napi_env env, napi_callback_info info); + static napi_value ClearData(napi_env env, napi_callback_info info); + static napi_value GetData(napi_env env, napi_callback_info info); + static napi_value SetData(napi_env env, napi_callback_info info); + static napi_value HasData(napi_env env, napi_callback_info info); + static napi_value IsRemoteData(napi_env env, napi_callback_info info); + static napi_value GetDataSource(napi_env env, napi_callback_info info); + static napi_value HasDataType(napi_env env, napi_callback_info info); + static napi_value ClearDataSync(napi_env env, napi_callback_info info); + static napi_value GetDataSync(napi_env env, napi_callback_info info); + static napi_value SetDataSync(napi_env env, napi_callback_info info); + static napi_value HasDataSync(napi_env env, napi_callback_info info); + static bool CheckAgrsOfOnAndOff(napi_env env, bool checkArgsCount, napi_value *argv, size_t argc); + static void SetObserver(napi_ref ref, std::shared_ptr observer); + static std::shared_ptr GetObserver(napi_env env, napi_value observer); + static void GetDataCommon(std::shared_ptr &context); + static void SetDataCommon(std::shared_ptr &context); + + std::shared_ptr value_; + std::shared_ptr pasteData_; + napi_env env_; + static thread_local std::map> observers_; +}; +} // namespace MiscServicesNapi +} // namespace OHOS +#endif \ No newline at end of file diff --git a/pasteboard/interfaces/kits/napi/src/async_call.cpp b/pasteboard/interfaces/kits/napi/src/async_call.cpp new file mode 100644 index 00000000..b5dcd8f6 --- /dev/null +++ b/pasteboard/interfaces/kits/napi/src/async_call.cpp @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#define LOG_TAG "PasteBoardAsyncCall" +#include "async_call.h" + +#include "pasteboard_hilog.h" + +using namespace OHOS::MiscServices; + +namespace OHOS::MiscServicesNapi { +AsyncCall::AsyncCall(napi_env env, napi_callback_info info, std::shared_ptr context, size_t pos) : env_(env) +{ + context_ = new AsyncContext(); + size_t argc = 6; + napi_value self = nullptr; + napi_value argv[6] = { nullptr }; + NAPI_CALL_RETURN_VOID(env, napi_get_cb_info(env, info, &argc, argv, &self, nullptr)); + pos = ((pos == ASYNC_DEFAULT_POS) ? (argc - 1) : pos); + if (pos >= 0 && pos < argc) { + napi_valuetype valueType = napi_undefined; + napi_typeof(env, argv[pos], &valueType); + if (valueType == napi_function) { + napi_create_reference(env, argv[pos], 1, &context_->callback); + } + } + napi_status status = (*context)(env, argc, argv, self); + if (status != napi_ok) { + return; + } + context_->ctx = std::move(context); + napi_create_reference(env, self, 1, &context_->self); +} + +AsyncCall::~AsyncCall() +{ + if (context_ == nullptr) { + return; + } + + DeleteContext(env_, context_); +} + +napi_value AsyncCall::Call(napi_env env, Context::ExecAction exec) +{ + if (context_ == nullptr) { + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_JS_NAPI, "context_ is null"); + return nullptr; + } + if (context_->ctx == nullptr) { + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_JS_NAPI, "context_->ctx is null"); + return nullptr; + } + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_JS_NAPI, "async call exec"); + context_->ctx->exec_ = std::move(exec); + napi_value promise = nullptr; + if (context_->callback == nullptr) { + napi_create_promise(env, &context_->defer, &promise); + } else { + napi_get_undefined(env, &promise); + } + napi_async_work work = context_->work; + napi_value resource = nullptr; + napi_create_string_utf8(env, LOG_TAG, NAPI_AUTO_LENGTH, &resource); + napi_create_async_work(env, nullptr, resource, AsyncCall::OnExecute, AsyncCall::OnComplete, context_, &work); + context_->work = work; + context_ = nullptr; + napi_queue_async_work_with_qos(env, work, napi_qos_user_initiated); + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_JS_NAPI, "async call exec"); + return promise; +} + +napi_value AsyncCall::SyncCall(napi_env env, AsyncCall::Context::ExecAction exec) +{ + if ((context_ == nullptr) || (context_->ctx == nullptr)) { + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_JS_NAPI, "context_ or context_->ctx is null"); + return nullptr; + } + context_->ctx->exec_ = std::move(exec); + napi_value promise = nullptr; + if (context_->callback == nullptr) { + napi_create_promise(env, &context_->defer, &promise); + } else { + napi_get_undefined(env, &promise); + } + AsyncCall::OnExecute(env, context_); + AsyncCall::OnComplete(env, napi_ok, context_); + return promise; +} + +void AsyncCall::OnExecute(napi_env env, void *data) +{ + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_JS_NAPI, "run the async runnable"); + AsyncContext *context = reinterpret_cast(data); + context->ctx->Exec(); +} + +void AsyncCall::OnComplete(napi_env env, napi_status status, void *data) +{ + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_JS_NAPI, "run the js callback function"); + AsyncContext *context = reinterpret_cast(data); + napi_value output = nullptr; + napi_status runStatus = (*context->ctx)(env, &output); + napi_value result[ARG_BUTT] = { 0 }; + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_JS_NAPI, + "run the js callback function:status[%{public}d]runStatus[%{public}d]", status, runStatus); + if (status == napi_ok && runStatus == napi_ok) { + napi_get_undefined(env, &result[ARG_ERROR]); + if (output != nullptr) { + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_JS_NAPI, "AsyncCall::OnComplete output != nullptr"); + result[ARG_DATA] = output; + } else { + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_JS_NAPI, "AsyncCall::OnComplete output == nullptr"); + napi_get_undefined(env, &result[ARG_DATA]); + } + } else { + napi_value errCode = nullptr; + napi_value message = nullptr; + std::string errMsg("async call failed"); + if (context->ctx->errCode_ != 0) { + napi_create_string_utf8(env, std::to_string(context->ctx->errCode_).c_str(), NAPI_AUTO_LENGTH, &errCode); + } + if (!context->ctx->errMsg_.empty()) { + errMsg = context->ctx->errMsg_; + } + napi_create_string_utf8(env, errMsg.c_str(), NAPI_AUTO_LENGTH, &message); + napi_create_error(env, errCode, message, &result[ARG_ERROR]); + napi_get_undefined(env, &result[ARG_DATA]); + } + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_JS_NAPI, + "run the js callback function:(context->defer != nullptr)?[%{public}d]", context->defer != nullptr); + if (context->defer != nullptr) { + // promise + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_JS_NAPI, "Promise to do!"); + if (status == napi_ok && runStatus == napi_ok) { + napi_resolve_deferred(env, context->defer, result[ARG_DATA]); + } else { + napi_reject_deferred(env, context->defer, result[ARG_ERROR]); + } + } else { + // callback + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_JS_NAPI, "Callback to do!"); + napi_value callback = nullptr; + napi_get_reference_value(env, context->callback, &callback); + napi_value returnValue; + napi_call_function(env, nullptr, callback, ARG_BUTT, result, &returnValue); + } + DeleteContext(env, context); +} +void AsyncCall::DeleteContext(napi_env env, AsyncContext *context) +{ + if (env != nullptr) { + napi_delete_reference(env, context->callback); + napi_delete_reference(env, context->self); + napi_delete_async_work(env, context->work); + } + delete context; +} +} // namespace OHOS::MiscServicesNapi \ No newline at end of file diff --git a/pasteboard/interfaces/kits/napi/src/napi_init.cpp b/pasteboard/interfaces/kits/napi/src/napi_init.cpp new file mode 100644 index 00000000..8db39791 --- /dev/null +++ b/pasteboard/interfaces/kits/napi/src/napi_init.cpp @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "napi_init.h" + +#include "pasteboard_napi.h" +#include "pastedata_napi.h" +#include "pastedata_record_napi.h" +#include "systempasteboard_napi.h" + +namespace OHOS { +namespace MiscServicesNapi { +EXTERN_C_START +/* + * Module export function + */ +static napi_value NapiInit(napi_env env, napi_value exports) +{ + /* + * Propertise define + */ + PasteDataRecordNapi::PasteDataRecordInit(env, exports); + PasteDataNapi::PasteDataInit(env, exports); + SystemPasteboardNapi::SystemPasteboardInit(env, exports); + PasteboardNapi::PasteBoardInit(env, exports); + return exports; +} +EXTERN_C_END + +/* + * Module define + */ +static napi_module _module = { .nm_version = 1, + .nm_flags = 0, + .nm_filename = "pasteboard", + .nm_register_func = NapiInit, + .nm_modname = "pasteboard", + .nm_priv = ((void *)0), + .reserved = { 0 } }; + +/* + * Module register function + */ +extern "C" __attribute__((constructor)) void RegisterModule(void) +{ + napi_module_register(&_module); +} +} // namespace MiscServicesNapi +} // namespace OHOS diff --git a/pasteboard/interfaces/kits/napi/src/napi_pasteboard.cpp b/pasteboard/interfaces/kits/napi/src/napi_pasteboard.cpp new file mode 100644 index 00000000..8eea8797 --- /dev/null +++ b/pasteboard/interfaces/kits/napi/src/napi_pasteboard.cpp @@ -0,0 +1,484 @@ +/* + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "napi_common_want.h" +#include "pasteboard_common.h" +#include "pasteboard_hilog.h" +#include "pasteboard_js_err.h" +#include "pasteboard_napi.h" +#include "pixel_map_napi.h" +#include "systempasteboard_napi.h" +#include "uri.h" +using namespace OHOS::MiscServices; +using namespace OHOS::Media; + +namespace OHOS { +namespace MiscServicesNapi { +constexpr size_t MAX_ARGS = 6; +napi_value PasteboardNapi::CreateHtmlRecord(napi_env env, napi_value in) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "CreateHtmlRecord is called!"); + std::string value; + bool ret = GetValue(env, in, value); + if (!ret) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "Failed to GetValue!"); + return nullptr; + } + napi_value instance = nullptr; + PasteDataRecordNapi::NewHtmlTextRecordInstance(env, value, instance); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "end."); + return instance; +} + +napi_value PasteboardNapi::CreatePlainTextRecord(napi_env env, napi_value in) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "CreatePlainTextRecord is called!"); + std::string value; + bool ret = GetValue(env, in, value); + if (!ret) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "Failed to GetValue!"); + return nullptr; + } + napi_value instance = nullptr; + PasteDataRecordNapi::NewPlainTextRecordInstance(env, value, instance); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "end."); + return instance; +} + +napi_value PasteboardNapi::CreateUriRecord(napi_env env, napi_value in) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "CreateUriRecord is called!"); + std::string value; + bool ret = GetValue(env, in, value); + if (!ret) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "Failed to GetValue!"); + return nullptr; + } + napi_value instance = nullptr; + PasteDataRecordNapi::NewUriRecordInstance(env, value, instance); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "end."); + return instance; +} + +napi_value PasteboardNapi::CreatePixelMapRecord(napi_env env, napi_value in) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "CreatePixelMapRecord is called!"); + std::shared_ptr pixelMap = PixelMapNapi::GetPixelMap(env, in); + if (pixelMap == nullptr) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "Failed to get pixelMap!"); + return nullptr; + } + napi_value instance = nullptr; + PasteDataRecordNapi::NewPixelMapRecordInstance(env, pixelMap, instance); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "end."); + return instance; +} + +napi_value PasteboardNapi::CreateWantRecord(napi_env env, napi_value in) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "CreateWantRecord is called!"); + AAFwk::Want want; + bool ret = OHOS::AppExecFwk::UnwrapWant(env, in, want); + if (!ret) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "Failed to unwrap want!"); + return nullptr; + } + napi_value instance = nullptr; + PasteDataRecordNapi::NewWantRecordInstance(env, std::make_shared(want), instance); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "end."); + return instance; +} + +// common function of CreateHtmlData, CreatePlainTextData, CreateUriData +PasteDataNapi *PasteboardNapi::CreateDataCommon(napi_env env, napi_value in, std::string &str, napi_value &instance) +{ + bool ret = GetValue(env, in, str); + if (!ret) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "GetValue failed"); + return nullptr; + } + NAPI_CALL(env, PasteDataNapi::NewInstance(env, instance)); + PasteDataNapi *obj = nullptr; + napi_status status = napi_unwrap(env, instance, reinterpret_cast(&obj)); + if ((status != napi_ok) || (obj == nullptr)) { + return nullptr; + } + return obj; +} + +napi_value PasteboardNapi::CreateHtmlData(napi_env env, napi_value in) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "CreateHtmlData is called!"); + std::string str; + napi_value instance = nullptr; + PasteDataNapi *obj = CreateDataCommon(env, in, str, instance); + if (obj == nullptr) { + return nullptr; + } + obj->value_ = PasteboardClient::GetInstance()->CreateHtmlData(str); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "end."); + return instance; +} + +napi_value PasteboardNapi::CreatePlainTextData(napi_env env, napi_value in) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "CreatePlainTextData is called!"); + std::string str; + napi_value instance = nullptr; + PasteDataNapi *obj = CreateDataCommon(env, in, str, instance); + if (obj == nullptr) { + return nullptr; + } + obj->value_ = PasteboardClient::GetInstance()->CreatePlainTextData(str); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "end."); + return instance; +} + +napi_value PasteboardNapi::CreateUriData(napi_env env, napi_value in) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "CreateUriData is called!"); + std::string str; + napi_value instance = nullptr; + PasteDataNapi *obj = CreateDataCommon(env, in, str, instance); + if (obj == nullptr) { + return nullptr; + } + obj->value_ = PasteboardClient::GetInstance()->CreateUriData(OHOS::Uri(str)); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "end."); + return instance; +} + +napi_value PasteboardNapi::CreatePixelMapData(napi_env env, napi_value in) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "CreatePixelMapData is called!"); + std::shared_ptr pixelMap = PixelMapNapi::GetPixelMap(env, in); + if (pixelMap == nullptr) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "Failed to get pixelMap!"); + return nullptr; + } + napi_value instance = nullptr; + NAPI_CALL(env, PasteDataNapi::NewInstance(env, instance)); + PasteDataNapi *obj = nullptr; + napi_status status = napi_unwrap(env, instance, reinterpret_cast(&obj)); + if ((status != napi_ok) || (obj == nullptr)) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "unwrap Failed!"); + return nullptr; + } + obj->value_ = PasteboardClient::GetInstance()->CreatePixelMapData(pixelMap); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "end."); + return instance; +} + +napi_value PasteboardNapi::CreateWantData(napi_env env, napi_value in) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "CreateWantData is called!"); + AAFwk::Want want; + bool ret = OHOS::AppExecFwk::UnwrapWant(env, in, want); + if (!ret) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "Failed to unwrap want!"); + return nullptr; + } + napi_value instance = nullptr; + NAPI_CALL(env, PasteDataNapi::NewInstance(env, instance)); + PasteDataNapi *obj = nullptr; + napi_status status = napi_unwrap(env, instance, reinterpret_cast(&obj)); + if ((status != napi_ok) || (obj == nullptr)) { + return nullptr; + } + obj->value_ = PasteboardClient::GetInstance()->CreateWantData(std::make_shared(want)); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "end."); + return instance; +} + +napi_value PasteboardNapi::JScreateHtmlTextRecord(napi_env env, napi_callback_info info) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "JScreateHtmlTextRecord is called!"); + size_t argc = MAX_ARGS; + napi_value argv[MAX_ARGS] = { 0 }; + napi_value thisVar = nullptr; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL)); + NAPI_ASSERT(env, argc > 0, "Wrong number of arguments"); + + return CreateHtmlRecord(env, argv[0]); +} + +napi_value PasteboardNapi::JScreateWantRecord(napi_env env, napi_callback_info info) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "JScreateWantRecord is called!"); + size_t argc = MAX_ARGS; + napi_value argv[MAX_ARGS] = { 0 }; + napi_value thisVar = nullptr; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL)); + NAPI_ASSERT(env, argc > 0, "Wrong number of arguments"); + napi_valuetype valueType = napi_undefined; + NAPI_CALL(env, napi_typeof(env, argv[0], &valueType)); + NAPI_ASSERT(env, valueType == napi_object, "Wrong argument type. Object expected."); + + return CreateWantRecord(env, argv[0]); +} + +napi_value PasteboardNapi::JScreateShareOption(napi_env env, napi_callback_info info) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "JScreateShareOption is called!"); + + napi_value jsShareOption = nullptr; + napi_create_object(env, &jsShareOption); + + napi_value jsInApp = CreateNapiNumber(env, static_cast(ShareOption::InApp)); + NAPI_CALL(env, napi_set_named_property(env, jsShareOption, "InApp", jsInApp)); + NAPI_CALL(env, napi_set_named_property(env, jsShareOption, "INAPP", jsInApp)); + + napi_value jsLocalDevice = CreateNapiNumber(env, static_cast(ShareOption::LocalDevice)); + NAPI_CALL(env, napi_set_named_property(env, jsShareOption, "LocalDevice", jsLocalDevice)); + NAPI_CALL(env, napi_set_named_property(env, jsShareOption, "LOCALDEVICE", jsLocalDevice)); + + napi_value jsCrossDevice = CreateNapiNumber(env, static_cast(ShareOption::CrossDevice)); + NAPI_CALL(env, napi_set_named_property(env, jsShareOption, "CrossDevice", jsCrossDevice)); + NAPI_CALL(env, napi_set_named_property(env, jsShareOption, "CROSSDEVICE", jsCrossDevice)); + + return jsShareOption; +} + +napi_value PasteboardNapi::JScreatePlainTextRecord(napi_env env, napi_callback_info info) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "JScreatePlainTextRecord is called!"); + size_t argc = MAX_ARGS; + napi_value argv[MAX_ARGS] = { 0 }; + napi_value thisVar = nullptr; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL)); + NAPI_ASSERT(env, argc > 0, "Wrong number of arguments"); + + return CreatePlainTextRecord(env, argv[0]); +} + +napi_value PasteboardNapi::JScreatePixelMapRecord(napi_env env, napi_callback_info info) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "JScreatePixelMapRecord is called!"); + size_t argc = MAX_ARGS; + napi_value argv[MAX_ARGS] = { 0 }; + napi_value thisVar = nullptr; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL)); + NAPI_ASSERT(env, argc > 0, "Wrong number of arguments"); + + napi_valuetype valueType = napi_undefined; + NAPI_CALL(env, napi_typeof(env, argv[0], &valueType)); + NAPI_ASSERT(env, valueType == napi_object, "Wrong argument type. Object expected."); + + return CreatePixelMapRecord(env, argv[0]); +} + +napi_value PasteboardNapi::JScreateUriRecord(napi_env env, napi_callback_info info) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "JScreateUriRecord is called!"); + size_t argc = MAX_ARGS; + napi_value argv[MAX_ARGS] = { 0 }; + napi_value thisVar = nullptr; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL)); + NAPI_ASSERT(env, argc > 0, "Wrong number of arguments"); + + return CreateUriRecord(env, argv[0]); +} + +napi_value PasteboardNapi::JSCreateRecord(napi_env env, napi_callback_info info) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "JSCreateRecord is called!"); + size_t argc = MAX_ARGS; + napi_value argv[MAX_ARGS] = { 0 }; + napi_value thisVar = nullptr; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL)); + std::string mimeType; + if (!CheckArgs(env, argv, argc, mimeType)) { + return nullptr; + } + auto it = createRecordMap_.find(mimeType); + if (it != createRecordMap_.end()) { + return (it->second)(env, argv[1]); + } + + void *data = nullptr; + size_t dataLen = 0; + NAPI_CALL(env, napi_get_arraybuffer_info(env, argv[1], &data, &dataLen)); + std::vector arrayBuf(reinterpret_cast(data), reinterpret_cast(data) + dataLen); + napi_value instance = nullptr; + PasteDataRecordNapi::NewKvRecordInstance(env, mimeType, arrayBuf, instance); + return instance; +} + +napi_value PasteboardNapi::JScreateHtmlData(napi_env env, napi_callback_info info) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "JScreateHtmlData is called!"); + size_t argc = MAX_ARGS; + napi_value argv[MAX_ARGS] = { 0 }; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr)); + NAPI_ASSERT(env, argc > 0, "Wrong number of arguments"); + + return CreateHtmlData(env, argv[0]); +} + +napi_value PasteboardNapi::JScreateWantData(napi_env env, napi_callback_info info) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "JScreateWantData is called!"); + size_t argc = MAX_ARGS; + napi_value argv[MAX_ARGS] = { 0 }; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr)); + NAPI_ASSERT(env, argc > 0, "Wrong number of arguments"); + napi_valuetype valueType = napi_undefined; + NAPI_CALL(env, napi_typeof(env, argv[0], &valueType)); + NAPI_ASSERT(env, valueType == napi_object, "Wrong argument type. Object expected."); + + return CreateWantData(env, argv[0]); +} + +napi_value PasteboardNapi::JScreatePlainTextData(napi_env env, napi_callback_info info) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "JScreatePlainTextData is called!"); + size_t argc = MAX_ARGS; + napi_value argv[MAX_ARGS] = { 0 }; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr)); + NAPI_ASSERT(env, argc > 0, "Wrong number of arguments"); + + return CreatePlainTextData(env, argv[0]); +} + +napi_value PasteboardNapi::JScreatePixelMapData(napi_env env, napi_callback_info info) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "JScreatePixelMapData is called!"); + size_t argc = MAX_ARGS; + napi_value argv[MAX_ARGS] = { 0 }; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr)); + NAPI_ASSERT(env, argc > 0, "Wrong number of arguments"); + napi_valuetype valueType = napi_undefined; + NAPI_CALL(env, napi_typeof(env, argv[0], &valueType)); + NAPI_ASSERT(env, valueType == napi_object, "Wrong argument type. Object expected."); + + return CreatePixelMapData(env, argv[0]); +} + +napi_value PasteboardNapi::JScreateUriData(napi_env env, napi_callback_info info) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "JScreateUriData is called!"); + size_t argc = MAX_ARGS; + napi_value argv[MAX_ARGS] = { 0 }; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr)); + NAPI_ASSERT(env, argc > 0, "Wrong number of arguments"); + + return CreateUriData(env, argv[0]); +} + +napi_value PasteboardNapi::JSCreateKvData( + napi_env env, const std::string &mimeType, const std::vector &arrayBuffer) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "JSCreateKvData is called!"); + + napi_value instance = nullptr; + NAPI_CALL(env, PasteDataNapi::NewInstance(env, instance)); + PasteDataNapi *obj = nullptr; + napi_status status = napi_unwrap(env, instance, reinterpret_cast(&obj)); + if ((status != napi_ok) || (obj == nullptr)) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "unwrap failed!"); + return nullptr; + } + + obj->value_ = PasteboardClient::GetInstance()->CreateKvData(mimeType, arrayBuffer); + return instance; +} + +napi_value PasteboardNapi::JSCreateData(napi_env env, napi_callback_info info) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "JSCreateData is called!"); + size_t argc = MAX_ARGS; + napi_value argv[MAX_ARGS] = { 0 }; + napi_value thisVar = nullptr; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL)); + std::string mimeType; + if (!CheckArgs(env, argv, argc, mimeType)) { + return nullptr; + } + auto it = createDataMap_.find(mimeType); + if (it != createDataMap_.end()) { + return (it->second)(env, argv[1]); + } + + void *data = nullptr; + size_t dataLen = 0; + NAPI_CALL(env, napi_get_arraybuffer_info(env, argv[1], &data, &dataLen)); + std::vector arrayBuf(reinterpret_cast(data), reinterpret_cast(data) + dataLen); + return JSCreateKvData(env, mimeType, arrayBuf); +} + +napi_value PasteboardNapi::JSgetSystemPasteboard(napi_env env, napi_callback_info info) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "JSgetSystemPasteboard is called!"); + size_t argc = MAX_ARGS; + napi_value argv[MAX_ARGS] = { 0 }; + napi_value thisVar = nullptr; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL)); + napi_value instance = nullptr; + napi_status status = SystemPasteboardNapi::NewInstance(env, instance); // 0 arguments + if (status != napi_ok) { + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "JSgetSystemPasteboard create instance failed"); + return NapiGetNull(env); + } + + return instance; +} + +napi_value PasteboardNapi::PasteBoardInit(napi_env env, napi_value exports) +{ + napi_property_descriptor desc[] = { DECLARE_NAPI_FUNCTION("createHtmlData", JScreateHtmlData), + DECLARE_NAPI_FUNCTION("createWantData", JScreateWantData), + DECLARE_NAPI_FUNCTION("createPlainTextData", JScreatePlainTextData), + DECLARE_NAPI_FUNCTION("createPixelMapData", JScreatePixelMapData), + DECLARE_NAPI_FUNCTION("createUriData", JScreateUriData), + DECLARE_NAPI_FUNCTION("createData", JSCreateData), + DECLARE_NAPI_FUNCTION("createHtmlTextRecord", JScreateHtmlTextRecord), + DECLARE_NAPI_FUNCTION("createWantRecord", JScreateWantRecord), + DECLARE_NAPI_FUNCTION("createPlainTextRecord", JScreatePlainTextRecord), + DECLARE_NAPI_FUNCTION("createPixelMapRecord", JScreatePixelMapRecord), + DECLARE_NAPI_FUNCTION("createUriRecord", JScreateUriRecord), + DECLARE_NAPI_FUNCTION("createRecord", JSCreateRecord), + DECLARE_NAPI_FUNCTION("getSystemPasteboard", JSgetSystemPasteboard), + DECLARE_NAPI_GETTER("ShareOption", JScreateShareOption), + DECLARE_NAPI_PROPERTY("MAX_RECORD_NUM", CreateNapiNumber(env, PasteData::MAX_RECORD_NUM)), + DECLARE_NAPI_PROPERTY("MIMETYPE_PIXELMAP", CreateNapiString(env, MIMETYPE_PIXELMAP)), + DECLARE_NAPI_PROPERTY("MIMETYPE_TEXT_HTML", CreateNapiString(env, MIMETYPE_TEXT_HTML)), + DECLARE_NAPI_PROPERTY("MIMETYPE_TEXT_WANT", CreateNapiString(env, MIMETYPE_TEXT_WANT)), + DECLARE_NAPI_PROPERTY("MIMETYPE_TEXT_PLAIN", CreateNapiString(env, MIMETYPE_TEXT_PLAIN)), + DECLARE_NAPI_PROPERTY("MIMETYPE_TEXT_URI", CreateNapiString(env, MIMETYPE_TEXT_URI)) }; + + NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc)); + + return exports; +} + +std::unordered_map PasteboardNapi::createRecordMap_ = { + { "text/html", &PasteboardNapi::CreateHtmlRecord }, { "text/plain", &PasteboardNapi::CreatePlainTextRecord }, + { "text/uri", &PasteboardNapi::CreateUriRecord }, { "pixelMap", &PasteboardNapi::CreatePixelMapRecord }, + { "text/want", &PasteboardNapi::CreateWantRecord } +}; + +std::unordered_map PasteboardNapi::createDataMap_ = { + { "text/html", &PasteboardNapi::CreateHtmlData }, { "text/plain", &PasteboardNapi::CreatePlainTextData }, + { "text/uri", &PasteboardNapi::CreateUriData }, { "pixelMap", &PasteboardNapi::CreatePixelMapData }, + { "text/want", &PasteboardNapi::CreateWantData } +}; +} // namespace MiscServicesNapi +} // namespace OHOS \ No newline at end of file diff --git a/pasteboard/interfaces/kits/napi/src/napi_pastedata.cpp b/pasteboard/interfaces/kits/napi/src/napi_pastedata.cpp new file mode 100644 index 00000000..b401babe --- /dev/null +++ b/pasteboard/interfaces/kits/napi/src/napi_pastedata.cpp @@ -0,0 +1,1042 @@ +/* + * Copyright (C) 2021-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include + +#include "napi_common_want.h" +#include "pasteboard_common.h" +#include "pasteboard_hilog.h" +#include "pasteboard_js_err.h" +#include "pastedata_napi.h" +#include "pastedata_record_napi.h" +using namespace OHOS::MiscServices; +using namespace OHOS::Media; + +namespace OHOS { +namespace MiscServicesNapi { +namespace { +constexpr int ARGC_TYPE_SET0 = 0; +constexpr int ARGC_TYPE_SET1 = 1; +constexpr int ARGC_TYPE_SET2 = 2; +const int32_t STR_MAX_SIZE = 256; +constexpr int32_t MIMETYPE_MAX_SIZE = 1024; +constexpr int32_t MAX_TEXT_LEN = 20 * 1024 * 1024; +constexpr size_t STR_TAIL_LENGTH = 1; +} // namespace +static thread_local napi_ref g_pasteData = nullptr; + +PasteDataNapi::PasteDataNapi() : env_(nullptr) +{ + value_ = std::make_shared(); +} + +PasteDataNapi::~PasteDataNapi() +{ +} + +napi_value PasteDataNapi::AddHtmlRecord(napi_env env, napi_callback_info info) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "AddHtmlRecord is called!"); + size_t argc = 1; + napi_value argv[1] = { 0 }; + napi_value thisVar = nullptr; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL)); + NAPI_ASSERT(env, argc > ARGC_TYPE_SET0, "Wrong number of arguments"); + + std::string str; + bool ret = GetValue(env, argv[0], str); + if (!ret) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "Failed to GetValue!"); + return nullptr; + } + + PasteDataNapi *obj = nullptr; + napi_status status = napi_unwrap(env, thisVar, reinterpret_cast(&obj)); + if ((status != napi_ok) || (obj == nullptr)) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "Get AddHtmlRecord object failed"); + return nullptr; + } + obj->value_->AddHtmlRecord(str); + return nullptr; +} + +napi_value PasteDataNapi::AddPixelMapRecord(napi_env env, napi_callback_info info) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "AddPixelMapRecord is called begin!"); + size_t argc = ARGC_TYPE_SET1; + napi_value argv[ARGC_TYPE_SET1] = { 0 }; + napi_value thisVar = nullptr; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL)); + NAPI_ASSERT(env, argc > ARGC_TYPE_SET0, "Wrong number of arguments"); + + napi_valuetype valueType = napi_undefined; + NAPI_CALL(env, napi_typeof(env, argv[0], &valueType)); + NAPI_ASSERT(env, valueType == napi_object, "Wrong argument type. Object expected."); + + std::shared_ptr pixelMap = PixelMapNapi::GetPixelMap(env, argv[0]); + if (pixelMap == nullptr) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "Failed to GetPixelMap!"); + return nullptr; + } + + PasteDataNapi *obj = nullptr; + napi_status status = napi_unwrap(env, thisVar, reinterpret_cast(&obj)); + if ((status != napi_ok) || (obj == nullptr)) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "unwrap failed"); + return nullptr; + } + obj->value_->AddPixelMapRecord(pixelMap); + return nullptr; +} + +napi_value PasteDataNapi::AddTextRecord(napi_env env, napi_callback_info info) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "AddTextRecord is called!"); + size_t argc = 1; + napi_value argv[1] = { 0 }; + napi_value thisVar = nullptr; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL)); + NAPI_ASSERT(env, argc > ARGC_TYPE_SET0, "Wrong number of arguments"); + + std::string str; + bool ret = GetValue(env, argv[0], str); + if (!ret) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "Failed to GetValue!"); + return nullptr; + } + + PasteDataNapi *obj = nullptr; + napi_status status = napi_unwrap(env, thisVar, reinterpret_cast(&obj)); + if ((status != napi_ok) || (obj == nullptr)) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "Get AddTextRecord object failed"); + return nullptr; + } + obj->value_->AddTextRecord(str); + return nullptr; +} + +napi_value PasteDataNapi::AddUriRecord(napi_env env, napi_callback_info info) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "AddUriRecord is called!"); + size_t argc = 1; + napi_value argv[1] = { 0 }; + napi_value thisVar = nullptr; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL)); + NAPI_ASSERT(env, argc > ARGC_TYPE_SET0, "Wrong number of arguments"); + + std::string str; + bool ret = GetValue(env, argv[0], str); + if (!ret) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "Failed to GetValue!"); + return nullptr; + } + + PasteDataNapi *obj = nullptr; + napi_status status = napi_unwrap(env, thisVar, reinterpret_cast(&obj)); + if ((status != napi_ok) || (obj == nullptr)) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "Get AddUriRecord object failed"); + return nullptr; + } + obj->value_->AddUriRecord(OHOS::Uri(str)); + return nullptr; +} + +napi_value PasteDataNapi::GetPrimaryHtml(napi_env env, napi_callback_info info) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "GetPrimaryHtml is called!"); + size_t argc = 1; + napi_value argv[1] = { 0 }; + napi_value thisVar = nullptr; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL)); + NAPI_ASSERT(env, argc >= ARGC_TYPE_SET0, "Wrong number of arguments"); + + PasteDataNapi *obj = nullptr; + napi_status status = napi_unwrap(env, thisVar, reinterpret_cast(&obj)); + if ((status != napi_ok) || (obj == nullptr)) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "Get GetPrimaryHtml object failed"); + return nullptr; + } + + std::shared_ptr p = obj->value_->GetPrimaryHtml(); + if (p == nullptr) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "Get GetPrimaryHtml failed"); + return nullptr; + } + + napi_value result = nullptr; + napi_create_string_utf8(env, p->c_str(), NAPI_AUTO_LENGTH, &result); + return result; +} + +napi_value PasteDataNapi::GetPrimaryPixelMap(napi_env env, napi_callback_info info) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "GetPrimaryPixelMap is called!"); + size_t argc = ARGC_TYPE_SET1; + napi_value argv[ARGC_TYPE_SET1] = { 0 }; + napi_value thisVar = nullptr; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL)); + NAPI_ASSERT(env, argc >= ARGC_TYPE_SET0, "Wrong number of arguments"); + + PasteDataNapi *obj = nullptr; + napi_status status = napi_unwrap(env, thisVar, reinterpret_cast(&obj)); + if ((status != napi_ok) || (obj == nullptr)) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "unwrap failed"); + return nullptr; + } + + std::shared_ptr pixelMap = obj->value_->GetPrimaryPixelMap(); + if (!pixelMap) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "pixelMap is nullptr"); + return nullptr; + } + + napi_value jsPixelMap = PixelMapNapi::CreatePixelMap(env, pixelMap); + return jsPixelMap; +} + +napi_value PasteDataNapi::GetPrimaryText(napi_env env, napi_callback_info info) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "GetPrimaryText is called!"); + size_t argc = 1; + napi_value argv[1] = { 0 }; + napi_value thisVar = nullptr; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL)); + NAPI_ASSERT(env, argc >= ARGC_TYPE_SET0, "Wrong number of arguments"); + + PasteDataNapi *obj = nullptr; + napi_status status = napi_unwrap(env, thisVar, reinterpret_cast(&obj)); + if ((status != napi_ok) || (obj == nullptr)) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "Get GetPrimaryText object failed"); + return nullptr; + } + + std::shared_ptr p = obj->value_->GetPrimaryText(); + if (p == nullptr) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "Get GetPrimaryText failed"); + return nullptr; + } + + napi_value result = nullptr; + napi_create_string_utf8(env, p->c_str(), NAPI_AUTO_LENGTH, &result); + return result; +} + +napi_value PasteDataNapi::GetPrimaryUri(napi_env env, napi_callback_info info) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "GetPrimaryUri is called!"); + size_t argc = 1; + napi_value argv[1] = { 0 }; + napi_value thisVar = nullptr; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL)); + NAPI_ASSERT(env, argc >= ARGC_TYPE_SET0, "Wrong number of arguments"); + + PasteDataNapi *obj = nullptr; + napi_status status = napi_unwrap(env, thisVar, reinterpret_cast(&obj)); + if ((status != napi_ok) || (obj == nullptr)) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "Get GetPrimaryUri object failed"); + return nullptr; + } + + std::shared_ptr p = obj->value_->GetPrimaryUri(); + if (p == nullptr) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "Get GetPrimaryUri failed"); + return nullptr; + } + + std::string text = p->ToString(); + napi_value result = nullptr; + napi_create_string_utf8(env, text.c_str(), NAPI_AUTO_LENGTH, &result); + return result; +} + +napi_value PasteDataNapi::HasMimeType(napi_env env, napi_callback_info info) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "HasMimeType is called!"); + size_t argc = 1; + napi_value argv[1] = { 0 }; + napi_value thisVar = nullptr; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL)); + if ((!CheckExpression(env, argc > ARGC_TYPE_SET0, JSErrorCode::INVALID_PARAMETERS, + "Parameter error. Wrong number of arguments.")) || + (!CheckArgsType(env, argv[0], napi_string, "Parameter error. The type of mimeType must be string."))) { + return nullptr; + } + + std::string mimeType; + if (!GetValue(env, argv[0], mimeType)) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "Failed to GetValue!"); + return nullptr; + } + + PasteDataNapi *obj = nullptr; + napi_status status = napi_unwrap(env, thisVar, reinterpret_cast(&obj)); + if ((status != napi_ok) || (obj == nullptr)) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "Get AddHtmlRecord object failed"); + return nullptr; + } + + bool ret = obj->value_->HasMimeType(mimeType); + napi_value result = nullptr; + napi_get_boolean(env, ret, &result); + return result; +} + +napi_value PasteDataNapi::HasType(napi_env env, napi_callback_info info) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "HasType is called!"); + return HasMimeType(env, info); +} + +PasteDataNapi *PasteDataNapi::RemoveAndGetRecordCommon(napi_env env, napi_callback_info info, uint32_t &index) +{ + size_t argc = 1; + napi_value argv[1] = { 0 }; + napi_value thisVar = nullptr; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL)); + + if ((!CheckExpression(env, argc > ARGC_TYPE_SET0, JSErrorCode::INVALID_PARAMETERS, + "Parameter error. Wrong number of arguments.")) || + (!CheckArgsType(env, argv[0], napi_number, "Parameter error. The type of mimeType must be number."))) { + return nullptr; + } + PasteDataNapi *obj = nullptr; + napi_status status = napi_unwrap(env, thisVar, reinterpret_cast(&obj)); + if ((status != napi_ok) || (obj == nullptr)) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "Get RemoveRecord object failed"); + return nullptr; + } + NAPI_CALL(env, napi_get_value_uint32(env, argv[0], &index)); + return obj; +} + +napi_value PasteDataNapi::RemoveRecordAt(napi_env env, napi_callback_info info) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "RemoveRecordAt is called!"); + uint32_t index = 0; + PasteDataNapi *obj = RemoveAndGetRecordCommon(env, info, index); + if (obj == nullptr) { + return nullptr; + } + bool ret = obj->value_->RemoveRecordAt(index); + napi_value result = nullptr; + napi_get_boolean(env, ret, &result); + return result; +} + +napi_value PasteDataNapi::RemoveRecord(napi_env env, napi_callback_info info) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "RemoveRecord is called!"); + uint32_t index = 0; + PasteDataNapi *obj = RemoveAndGetRecordCommon(env, info, index); + if (obj == nullptr || !CheckExpression(env, index < obj->value_->GetRecordCount(), + JSErrorCode::OUT_OF_RANGE, "index out of range.")) { + return nullptr; + } + obj->value_->RemoveRecordAt(index); + return nullptr; +} + +napi_value PasteDataNapi::GetPrimaryMimeType(napi_env env, napi_callback_info info) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "GetPrimaryMimeType is called!"); + size_t argc = 1; + napi_value argv[1] = { 0 }; + napi_value thisVar = nullptr; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL)); + NAPI_ASSERT(env, argc >= ARGC_TYPE_SET0, "Wrong number of arguments"); + + PasteDataNapi *obj = nullptr; + napi_status status = napi_unwrap(env, thisVar, reinterpret_cast(&obj)); + if ((status != napi_ok) || (obj == nullptr)) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "Get GetPrimaryMimeType object failed"); + return nullptr; + } + std::shared_ptr mimeType = obj->value_->GetPrimaryMimeType(); + if (mimeType == nullptr) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "Get GetPrimaryMimeType failed"); + return nullptr; + } + napi_value result = nullptr; + napi_create_string_utf8(env, mimeType->c_str(), NAPI_AUTO_LENGTH, &result); + + return result; +} + +napi_value PasteDataNapi::GetRecordCount(napi_env env, napi_callback_info info) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "GetRecordCount is called!"); + size_t argc = 1; + napi_value argv[1] = { 0 }; + napi_value thisVar = nullptr; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL)); + NAPI_ASSERT(env, argc >= ARGC_TYPE_SET0, "Wrong number of arguments"); + + PasteDataNapi *obj = nullptr; + napi_status status = napi_unwrap(env, thisVar, reinterpret_cast(&obj)); + if ((status != napi_ok) || (obj == nullptr)) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "Get GetRecordCount object failed"); + return nullptr; + } + + size_t count = obj->value_->GetRecordCount(); + napi_value result = nullptr; + napi_create_int64(env, count, &result); + + return result; +} + +napi_value PasteDataNapi::GetTag(napi_env env, napi_callback_info info) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "GetTag is called!"); + size_t argc = 1; + napi_value argv[1] = { 0 }; + napi_value thisVar = nullptr; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL)); + NAPI_ASSERT(env, argc >= ARGC_TYPE_SET0, "Wrong number of arguments"); + + PasteDataNapi *obj = nullptr; + napi_status status = napi_unwrap(env, thisVar, reinterpret_cast(&obj)); + if ((status != napi_ok) || (obj == nullptr)) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "Get GetTag object failed"); + return nullptr; + } + std::string tag = obj->value_->GetTag(); + napi_value result = nullptr; + napi_create_string_utf8(env, tag.c_str(), NAPI_AUTO_LENGTH, &result); + + return result; +} + +napi_value PasteDataNapi::GetMimeTypes(napi_env env, napi_callback_info info) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "GetMimeTypes is called!"); + size_t argc = 1; + napi_value argv[1] = { 0 }; + napi_value thisVar = nullptr; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL)); + NAPI_ASSERT(env, argc >= ARGC_TYPE_SET0, "Wrong number of arguments"); + + PasteDataNapi *obj = nullptr; + napi_status status = napi_unwrap(env, thisVar, reinterpret_cast(&obj)); + if ((status != napi_ok) || (obj == nullptr)) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "Get GetMimeTypes object failed"); + return nullptr; + } + std::vector mimeTypes = obj->value_->GetMimeTypes(); + if (mimeTypes.size() == 0) { + return nullptr; + } + + napi_value nMimeTypes = nullptr; + if (napi_create_array(env, &nMimeTypes) != napi_ok) { + return nullptr; + } + size_t index = 0; + napi_value value = nullptr; + for (auto type : mimeTypes) { + napi_create_string_utf8(env, type.c_str(), NAPI_AUTO_LENGTH, &value); + napi_set_element(env, nMimeTypes, index, value); + index++; + } + return nMimeTypes; +} + +void PasteDataNapi::AddRecord(napi_env env, napi_value *argv, size_t argc, PasteDataNapi *obj) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "AddRecordV9!"); + std::string mimeType; + if (!CheckArgs(env, argv, argc, mimeType)) { + return; + } + bool isArrayBuffer = false; + NAPI_CALL_RETURN_VOID(env, napi_is_arraybuffer(env, argv[1], &isArrayBuffer)); + if (isArrayBuffer) { + void *data = nullptr; + size_t dataLen = 0; + NAPI_CALL_RETURN_VOID(env, napi_get_arraybuffer_info(env, argv[1], &data, &dataLen)); + obj->value_->AddKvRecord(mimeType, + std::vector(reinterpret_cast(data), reinterpret_cast(data) + dataLen)); + return; + } + if (mimeType == MIMETYPE_PIXELMAP) { + std::shared_ptr pixelMap = PixelMapNapi::GetPixelMap(env, argv[1]); + obj->value_->AddPixelMapRecord(pixelMap); + return; + } else if (mimeType == MIMETYPE_TEXT_WANT) { + OHOS::AAFwk::Want want; + AppExecFwk::UnwrapWant(env, argv[1], want); + obj->value_->AddWantRecord(std::make_shared(want)); + return; + } + + std::string str; + bool ret = GetValue(env, argv[1], str); + if (!ret) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "Failed to GetValue!"); + return; + } + if (mimeType == MIMETYPE_TEXT_HTML) { + obj->value_->AddHtmlRecord(str); + } else if (mimeType == MIMETYPE_TEXT_PLAIN) { + obj->value_->AddTextRecord(str); + } else { + obj->value_->AddUriRecord(OHOS::Uri(str)); + } +} + +bool PasteDataNapi::SetStringProp( + napi_env env, const std::string &propName, napi_value &propValueNapi, PasteDataRecord::Builder &builder) +{ + std::string propValue; + bool ret = GetValue(env, propValueNapi, propValue); + if (!ret) { + return false; + } + if ((propName == "mimeType") && (propValue.size() <= MIMETYPE_MAX_SIZE)) { + builder.SetMimeType(propValue); + } else if ((propName == "htmlText") && (propValue.size() <= MAX_TEXT_LEN)) { + builder.SetHtmlText(std::make_shared(propValue)); + } else if ((propName == "plainText") && (propValue.size() <= MAX_TEXT_LEN)) { + builder.SetPlainText(std::make_shared(propValue)); + } else if (propName == "uri") { + builder.SetUri(std::make_shared(Uri(propValue))); + } else { + return false; + } + return true; +} + +std::shared_ptr PasteDataNapi::ParseRecord(napi_env env, napi_value &recordNapi) +{ + napi_value propNames = nullptr; + NAPI_CALL(env, napi_get_property_names(env, recordNapi, &propNames)); + uint32_t propNameNums = 0; + NAPI_CALL(env, napi_get_array_length(env, propNames, &propNameNums)); + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_JS_NAPI, "propNameNums = %{public}d", propNameNums); + PasteDataRecord::Builder builder(""); + for (uint32_t i = 0; i < propNameNums; i++) { + napi_value propNameNapi = nullptr; + NAPI_CALL(env, napi_get_element(env, propNames, i, &propNameNapi)); + size_t len = 0; + char str[STR_MAX_SIZE] = { 0 }; + NAPI_CALL(env, napi_get_value_string_utf8(env, propNameNapi, str, STR_MAX_SIZE - STR_TAIL_LENGTH, &len)); + napi_value propValueNapi = nullptr; + NAPI_CALL(env, napi_get_named_property(env, recordNapi, str, &propValueNapi)); + std::string propName = str; + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_JS_NAPI, "propName = %{public}s,", propName.c_str()); + + if (propName == "mimeType" || propName == "htmlText" || propName == "plainText" || propName == "uri") { + if (!SetStringProp(env, propName, propValueNapi, builder)) { + return nullptr; + } + } else if (propName == "want") { + AAFwk::Want want; + if (OHOS::AppExecFwk::UnwrapWant(env, propValueNapi, want) != true) { + return nullptr; + } + builder.SetWant(std::make_shared(want)); + } else if (propName == "pixelMap") { + std::shared_ptr pixelMap = PixelMapNapi::GetPixelMap(env, propValueNapi); + if (pixelMap == nullptr) { + return nullptr; + } + builder.SetPixelMap(pixelMap); + } else if (propName == "data") { + std::shared_ptr customData = PasteDataRecordNapi::GetNativeKvData(env, propValueNapi); + if (customData == nullptr) { + return nullptr; + } + builder.SetCustomData(customData); + } + } + return builder.Build(); +} + +void PasteDataNapi::AddRecord(napi_env env, napi_value argv, PasteDataNapi *obj) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "AddPasteDataRecord!"); + + napi_valuetype valueType = napi_undefined; + NAPI_CALL_RETURN_VOID(env, napi_typeof(env, argv, &valueType)); + NAPI_ASSERT_RETURN_VOID(env, valueType == napi_object, "Wrong argument type. Object expected."); + + std::shared_ptr pasteDataRecord = ParseRecord(env, argv); + if (pasteDataRecord == nullptr) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "ParseRecord failed!"); + return; + } + obj->value_->AddRecord(*pasteDataRecord); +} + +napi_value PasteDataNapi::AddRecord(napi_env env, napi_callback_info info) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "AddRecord is called!"); + size_t argc = ARGC_TYPE_SET2; + napi_value argv[ARGC_TYPE_SET2] = { 0 }; + napi_value thisVar = nullptr; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL)); + NAPI_ASSERT(env, argc > 0, "Wrong number of arguments"); + PasteDataNapi *obj = nullptr; + napi_status status = napi_unwrap(env, thisVar, reinterpret_cast(&obj)); + if ((status != napi_ok) || (obj == nullptr)) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "Get AddRecord object failed"); + return nullptr; + } + + if (argc == ARGC_TYPE_SET1) { + AddRecord(env, argv[0], obj); + return nullptr; + } + AddRecord(env, argv, argc, obj); + return nullptr; +} + +napi_value PasteDataNapi::ReplaceRecordAt(napi_env env, napi_callback_info info) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "ReplaceRecordAt is called!"); + size_t argc = ARGC_TYPE_SET2; + napi_value argv[ARGC_TYPE_SET2] = { 0 }; + napi_value thisVar = nullptr; + napi_value result = nullptr; + napi_get_boolean(env, false, &result); + + NAPI_CALL_BASE(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL), result); + NAPI_ASSERT(env, argc > ARGC_TYPE_SET1, "Wrong number of arguments"); + napi_valuetype valueType = napi_undefined; + NAPI_CALL_BASE(env, napi_typeof(env, argv[0], &valueType), result); + NAPI_ASSERT(env, valueType == napi_number, "Wrong argument type. number expected."); + NAPI_CALL_BASE(env, napi_typeof(env, argv[1], &valueType), result); + NAPI_ASSERT(env, valueType == napi_object, "Wrong argument type. Object expected."); + + PasteDataNapi *obj = nullptr; + napi_status status = napi_unwrap(env, thisVar, reinterpret_cast(&obj)); + if ((status != napi_ok) || (obj == nullptr)) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "Get ReplaceRecordAt object failed"); + return result; + } + + std::shared_ptr pasteDataRecord = ParseRecord(env, argv[1]); + if (pasteDataRecord == nullptr) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "ParseRecord failed!"); + return result; + } + + int64_t number = 0; + napi_get_value_int64(env, argv[0], &number); + bool ret = obj->value_->ReplaceRecordAt(number, pasteDataRecord); + napi_get_boolean(env, ret, &result); + + return result; +} + +napi_value PasteDataNapi::ReplaceRecord(napi_env env, napi_callback_info info) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "ReplaceRecord is called!"); + size_t argc = ARGC_TYPE_SET2; + napi_value argv[ARGC_TYPE_SET2] = { 0 }; + napi_value thisVar = nullptr; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL)); + if (!CheckExpression(env, argc > ARGC_TYPE_SET1, JSErrorCode::INVALID_PARAMETERS, "Wrong number of arguments.") || + !CheckArgsType(env, argv[0], napi_number, "The type of mimeType must be number.")) { + return nullptr; + } + + PasteDataNapi *obj = nullptr; + napi_status status = napi_unwrap(env, thisVar, reinterpret_cast(&obj)); + if ((status != napi_ok) || (obj == nullptr)) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "Get ReplaceRecord object failed"); + return nullptr; + } + uint32_t index = 0; + NAPI_CALL(env, napi_get_value_uint32(env, argv[0], &index)); + if (!CheckExpression(env, index < obj->value_->GetRecordCount(), + JSErrorCode::OUT_OF_RANGE, "index out of range.")) { + return nullptr; + } + + if (!CheckArgsType(env, argv[1], napi_object, "The type of record must be PasteDataRecord.")) { + return nullptr; + } + std::shared_ptr pasteDataRecord = ParseRecord(env, argv[1]); + if (!CheckExpression(env, pasteDataRecord != nullptr, JSErrorCode::INVALID_PARAMETERS, + "The type of record must be PasteDataRecord.")) { + return nullptr; + } + obj->value_->ReplaceRecordAt(index, pasteDataRecord); + return nullptr; +} + +napi_value PasteDataNapi::AddWantRecord(napi_env env, napi_callback_info info) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "AddWantRecord is called!"); + size_t argc = 1; + napi_value argv[1] = { 0 }; + napi_value thisVar = nullptr; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL)); + NAPI_ASSERT(env, argc > ARGC_TYPE_SET0, "Wrong number of arguments"); + + napi_valuetype valueType = napi_undefined; + NAPI_CALL(env, napi_typeof(env, argv[0], &valueType)); + NAPI_ASSERT(env, valueType == napi_object, "Wrong argument type. Object expected."); + OHOS::AAFwk::Want want; + if (!OHOS::AppExecFwk::UnwrapWant(env, argv[0], want)) { + return nullptr; + } + + PasteDataNapi *obj = nullptr; + napi_status status = napi_unwrap(env, thisVar, reinterpret_cast(&obj)); + if ((status != napi_ok) || (obj == nullptr)) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "Get AddWantRecord object failed"); + return nullptr; + } + + obj->value_->AddWantRecord(std::make_shared(want)); + return nullptr; +} + +napi_value PasteDataNapi::GetPrimaryWant(napi_env env, napi_callback_info info) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "GetPrimaryWant is called!"); + size_t argc = 1; + napi_value argv[1] = { 0 }; + napi_value thisVar = nullptr; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL)); + NAPI_ASSERT(env, argc >= ARGC_TYPE_SET0, "Wrong number of arguments"); + + PasteDataNapi *obj = nullptr; + napi_status status = napi_unwrap(env, thisVar, reinterpret_cast(&obj)); + if ((status != napi_ok) || (obj == nullptr)) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "Get GetPrimaryWant object failed"); + return nullptr; + } + + std::shared_ptr want = obj->value_->GetPrimaryWant(); + if (!want) { + return nullptr; + } + return OHOS::AppExecFwk::WrapWant(env, *want); +} + +bool PasteDataNapi::SetNapiProperty(napi_env env, const PasteDataProperty &property, napi_value &nProperty) +{ + napi_value value = nullptr; + napi_value arr = nullptr; + int count = 0; + + // additions : {[key: string]: object} + value = OHOS::AppExecFwk::WrapWantParams(env, property.additions); + napi_set_named_property(env, nProperty, "additions", value); + + // mimeTypes: Array + napi_create_array(env, &arr); + for (auto vec : property.mimeTypes) { + napi_create_string_utf8(env, vec.c_str(), NAPI_AUTO_LENGTH, &value); + napi_set_element(env, arr, count, value); + count++; + } + napi_set_named_property(env, nProperty, "mimeTypes", arr); + + // tag: string + napi_create_string_utf8(env, property.tag.c_str(), NAPI_AUTO_LENGTH, &value); + napi_set_named_property(env, nProperty, "tag", value); + + // timestamp: number + napi_create_int64(env, property.timestamp, &value); + napi_set_named_property(env, nProperty, "timestamp", value); + + // localOnly: boolean + napi_get_boolean(env, property.localOnly, &value); + napi_set_named_property(env, nProperty, "localOnly", value); + + napi_create_int32(env, static_cast(property.shareOption), &value); + napi_set_named_property(env, nProperty, "shareOption", value); + return true; +} + +napi_value PasteDataNapi::GetProperty(napi_env env, napi_callback_info info) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "GetProperty is called!"); + size_t argc = 1; + napi_value argv[1] = { 0 }; + napi_value thisVar = nullptr; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL)); + NAPI_ASSERT(env, argc >= ARGC_TYPE_SET0, "Wrong number of arguments"); + + PasteDataNapi *obj = nullptr; + napi_status status = napi_unwrap(env, thisVar, reinterpret_cast(&obj)); + if ((status != napi_ok) || (obj == nullptr)) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "Get GetProperty object failed"); + return nullptr; + } + PasteDataProperty property = obj->value_->GetProperty(); + napi_value nProperty = nullptr; + napi_create_object(env, &nProperty); + if (!SetNapiProperty(env, property, nProperty)) { + return nullptr; + } + return nProperty; +} + +napi_value PasteDataNapi::GetRecordAt(napi_env env, napi_callback_info info) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "GetRecordAt is called!"); + uint32_t index = 0; + PasteDataNapi *obj = RemoveAndGetRecordCommon(env, info, index); + if (obj == nullptr) { + return nullptr; + } + + std::shared_ptr record = obj->value_->GetRecordAt(index); + napi_value instance = nullptr; + PasteDataRecordNapi::NewInstanceByRecord(env, instance, record); + return instance; +} + +napi_value PasteDataNapi::GetRecord(napi_env env, napi_callback_info info) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "GetRecord is called!"); + uint32_t index = 0; + PasteDataNapi *obj = RemoveAndGetRecordCommon(env, info, index); + if (obj == nullptr || !CheckExpression(env, index < obj->value_->GetRecordCount(), + JSErrorCode::OUT_OF_RANGE, "index out of range.")) { + return nullptr; + } + + std::shared_ptr record = obj->value_->GetRecordAt(index); + napi_value instance = nullptr; + PasteDataRecordNapi::NewInstanceByRecord(env, instance, record); + return instance; +} + +void PasteDataNapi::SetProperty(napi_env env, napi_value in, PasteDataNapi *obj) +{ + napi_value propertyNames = nullptr; + NAPI_CALL_RETURN_VOID(env, napi_get_property_names(env, in, &propertyNames)); + uint32_t propertyNamesNum = 0; + NAPI_CALL_RETURN_VOID(env, napi_get_array_length(env, propertyNames, &propertyNamesNum)); + bool localOnlyValue = false; + int32_t shareOptionValue = ShareOption::CrossDevice; + for (uint32_t i = 0; i < propertyNamesNum; i++) { + napi_value propertyNameNapi = nullptr; + NAPI_CALL_RETURN_VOID(env, napi_get_element(env, propertyNames, i, &propertyNameNapi)); + size_t len = 0; + char str[STR_MAX_SIZE] = { 0 }; + NAPI_CALL_RETURN_VOID(env, napi_get_value_string_utf8(env, propertyNameNapi, str, STR_MAX_SIZE, &len)); + std::string propertyName = str; + napi_value propertyNameValueNapi = nullptr; + NAPI_CALL_RETURN_VOID(env, napi_get_named_property(env, in, str, &propertyNameValueNapi)); + if (propertyName == "localOnly") { + NAPI_CALL_RETURN_VOID(env, napi_get_value_bool(env, propertyNameValueNapi, &localOnlyValue)); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "localOnlyValue = %{public}d", localOnlyValue); + } + if (propertyName == "shareOption") { + NAPI_CALL_RETURN_VOID(env, napi_get_value_int32(env, propertyNameValueNapi, &shareOptionValue)); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "shareOptionValue = %{public}d", shareOptionValue); + } + if (propertyName == "tag") { + char tagValue[STR_MAX_SIZE] = { 0 }; + size_t tagValueLen = 0; + NAPI_CALL_RETURN_VOID(env, + napi_get_value_string_utf8(env, propertyNameValueNapi, tagValue, STR_MAX_SIZE, &tagValueLen)); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "tagValue = %{public}s", tagValue); + std::string tagValueStr = tagValue; + obj->value_->SetTag(tagValueStr); + } + if (propertyName == "additions") { + AAFwk::WantParams additions; + bool ret = OHOS::AppExecFwk::UnwrapWantParams(env, propertyNameValueNapi, additions); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "additions ret = %{public}d", ret); + obj->value_->SetAdditions(additions); + } + } + localOnlyValue = shareOptionValue == ShareOption::CrossDevice ? false : true; + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_CLIENT, "localOnly final Value = %{public}d", localOnlyValue); + obj->value_->SetLocalOnly(localOnlyValue); + obj->value_->SetShareOption(static_cast(shareOptionValue)); +} + +bool PasteDataNapi::IsProperty(napi_env env, napi_value in) +{ + napi_valuetype valueType = napi_undefined; + NAPI_CALL_BASE(env, napi_typeof(env, in, &valueType), false); + if (valueType != napi_object) { + return false; + } + napi_value propertyNames = nullptr; + NAPI_CALL_BASE(env, napi_get_property_names(env, in, &propertyNames), false); + uint32_t propertyNamesNum = 0; + NAPI_CALL_BASE(env, napi_get_array_length(env, propertyNames, &propertyNamesNum), false); + bool hasProperty = false; + const char *key[] = { "additions", "mimeTypes", "tag", "timestamp", "localOnly", "shareOption" }; + const napi_valuetype type[] = { napi_object, napi_object, napi_string, napi_number, napi_boolean, napi_number }; + napi_value propertyValue = nullptr; + for (uint32_t i = 0; i < propertyNamesNum; i++) { + NAPI_CALL_BASE(env, napi_has_named_property(env, in, key[i], &hasProperty), false); + if (!hasProperty) { + return false; + } + NAPI_CALL_BASE(env, napi_get_named_property(env, in, key[i], &propertyValue), false); + if (i == ARGC_TYPE_SET1) { + bool isArray = false; + NAPI_CALL_BASE(env, napi_is_array(env, propertyValue, &isArray), false); + if (!isArray) { + return false; + } + continue; + } + NAPI_CALL_BASE(env, napi_typeof(env, propertyValue, &valueType), false); + if (valueType != type[i]) { + return false; + } + } + return true; +} + +napi_value PasteDataNapi::SetProperty(napi_env env, napi_callback_info info) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "SetProperty is called!"); + size_t argc = ARGC_TYPE_SET1; + napi_value argv[ARGC_TYPE_SET1] = { 0 }; + napi_value thisVar = nullptr; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL)); + if (!CheckExpression(env, argc > ARGC_TYPE_SET0, JSErrorCode::INVALID_PARAMETERS, + "Parameter error. Wrong number of arguments.") || + !CheckExpression(env, IsProperty(env, argv[0]), JSErrorCode::INVALID_PARAMETERS, + "Parameter error. The type of property must be PasteDataProperty.")) { + return nullptr; + } + + PasteDataNapi *obj = nullptr; + napi_status status = napi_unwrap(env, thisVar, reinterpret_cast(&obj)); + if ((status != napi_ok) || (obj == nullptr)) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "napi_unwrap failed"); + return nullptr; + } + SetProperty(env, argv[0], obj); + return nullptr; +} + +napi_value PasteDataNapi::PasteDataInit(napi_env env, napi_value exports) +{ + napi_status status = napi_ok; + napi_property_descriptor descriptors[] = { DECLARE_NAPI_FUNCTION("addHtmlRecord", AddHtmlRecord), + DECLARE_NAPI_FUNCTION("addWantRecord", AddWantRecord), DECLARE_NAPI_FUNCTION("addRecord", AddRecord), + DECLARE_NAPI_FUNCTION("addTextRecord", AddTextRecord), DECLARE_NAPI_FUNCTION("addUriRecord", AddUriRecord), + DECLARE_NAPI_FUNCTION("addPixelMapRecord", AddPixelMapRecord), + DECLARE_NAPI_FUNCTION("getMimeTypes", GetMimeTypes), DECLARE_NAPI_FUNCTION("getPrimaryHtml", GetPrimaryHtml), + DECLARE_NAPI_FUNCTION("getPrimaryWant", GetPrimaryWant), + DECLARE_NAPI_FUNCTION("getPrimaryMimeType", GetPrimaryMimeType), + DECLARE_NAPI_FUNCTION("getPrimaryText", GetPrimaryText), DECLARE_NAPI_FUNCTION("getPrimaryUri", GetPrimaryUri), + DECLARE_NAPI_FUNCTION("getPrimaryPixelMap", GetPrimaryPixelMap), + DECLARE_NAPI_FUNCTION("getProperty", GetProperty), DECLARE_NAPI_FUNCTION("getRecordAt", GetRecordAt), + DECLARE_NAPI_FUNCTION("getRecord", GetRecord), DECLARE_NAPI_FUNCTION("getRecordCount", GetRecordCount), + DECLARE_NAPI_FUNCTION("getTag", GetTag), DECLARE_NAPI_FUNCTION("hasMimeType", HasMimeType), + DECLARE_NAPI_FUNCTION("hasType", HasType), DECLARE_NAPI_FUNCTION("removeRecordAt", RemoveRecordAt), + DECLARE_NAPI_FUNCTION("removeRecord", RemoveRecord), DECLARE_NAPI_FUNCTION("replaceRecordAt", ReplaceRecordAt), + DECLARE_NAPI_FUNCTION("replaceRecord", ReplaceRecord), DECLARE_NAPI_FUNCTION("setProperty", SetProperty) }; + + napi_value constructor; + napi_define_class(env, "PasteData", NAPI_AUTO_LENGTH, New, nullptr, + sizeof(descriptors) / sizeof(napi_property_descriptor), descriptors, &constructor); + if (status != napi_ok) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "Failed to define class at Init"); + return nullptr; + } + + status = napi_create_reference(env, constructor, 1, &g_pasteData); + if (status != napi_ok) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "PasteDataNapi Init create reference failed"); + return nullptr; + } + napi_set_named_property(env, exports, "PasteData", constructor); + return exports; +} + +void PasteDataNapi::Destructor(napi_env env, void *nativeObject, void *finalize_hint) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "Destructor"); + PasteDataNapi *obj = static_cast(nativeObject); + delete obj; +} + +napi_value PasteDataNapi::New(napi_env env, napi_callback_info info) +{ + size_t argc = ARGC_TYPE_SET1; + napi_value argv[1] = { 0 }; + napi_value thisVar = nullptr; + napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr); + + // get native object + PasteDataNapi *obj = new PasteDataNapi(); + obj->env_ = env; + NAPI_CALL(env, napi_wrap(env, thisVar, obj, PasteDataNapi::Destructor, + nullptr, // finalize_hint + nullptr)); + return thisVar; +} + +napi_status PasteDataNapi::NewInstance(napi_env env, napi_value &instance) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "enter"); + napi_status status; + napi_value constructor; + status = napi_get_reference_value(env, g_pasteData, &constructor); + if (status != napi_ok) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "get reference failed"); + return status; + } + + status = napi_new_instance(env, constructor, 0, nullptr, &instance); + if (status != napi_ok) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "new instance failed"); + return status; + } + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "new instance ok"); + return napi_ok; +} + +bool PasteDataNapi::IsPasteData(napi_env env, napi_value in) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "enter"); + napi_valuetype type = napi_undefined; + NAPI_CALL_BASE(env, napi_typeof(env, in, &type), false); + if (type != napi_object) { + return false; + } + napi_value constructor; + bool isPasteData = false; + NAPI_CALL_BASE(env, napi_get_reference_value(env, g_pasteData, &constructor), false); + NAPI_CALL_BASE(env, napi_instanceof(env, in, constructor, &isPasteData), false); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "isPasteData is [%{public}d]", isPasteData); + return isPasteData; +} +} // namespace MiscServicesNapi +} // namespace OHOS diff --git a/pasteboard/interfaces/kits/napi/src/napi_pastedata_record.cpp b/pasteboard/interfaces/kits/napi/src/napi_pastedata_record.cpp new file mode 100644 index 00000000..1e0c49e3 --- /dev/null +++ b/pasteboard/interfaces/kits/napi/src/napi_pastedata_record.cpp @@ -0,0 +1,405 @@ +/* + * Copyright (C) 2021-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "async_call.h" +#include "napi_common_want.h" +#include "paste_data_record.h" +#include "pasteboard_common.h" +#include "pasteboard_hilog.h" +#include "pasteboard_js_err.h" +#include "pastedata_napi.h" +#include "pastedata_record_napi.h" + +using namespace OHOS::MiscServices; +using namespace OHOS::Media; + +namespace OHOS { +namespace MiscServicesNapi { +static thread_local napi_ref g_pasteDataRecord = nullptr; +const int ARGC_TYPE_SET0 = 0; +const int ARGC_TYPE_SET1 = 1; +constexpr int32_t MIMETYPE_MAX_SIZE = 1024; + +PasteDataRecordNapi::PasteDataRecordNapi() : env_(nullptr) +{ +} + +PasteDataRecordNapi::~PasteDataRecordNapi() +{ +} + +bool PasteDataRecordNapi::NewInstanceByRecord( + napi_env env, napi_value &instance, const std::shared_ptr &record) +{ + NAPI_CALL_BASE(env, PasteDataRecordNapi::NewInstance(env, instance), false); + PasteDataRecordNapi *obj = nullptr; + napi_status status = napi_unwrap(env, instance, reinterpret_cast(&obj)); + if ((status != napi_ok) || (obj == nullptr)) { + return false; + } + obj->value_ = record; + obj->JSFillInstance(env, instance); + return true; +} + +bool PasteDataRecordNapi::NewHtmlTextRecordInstance(napi_env env, const std::string &text, napi_value &instance) +{ + NAPI_CALL_BASE(env, PasteDataRecordNapi::NewInstance(env, instance), false); + PasteDataRecordNapi *obj = nullptr; + napi_status status = napi_unwrap(env, instance, reinterpret_cast(&obj)); + if ((status != napi_ok) || (obj == nullptr)) { + return false; + } + obj->value_ = PasteboardClient::GetInstance()->CreateHtmlTextRecord(text); + obj->JSFillInstance(env, instance); + return true; +} + +bool PasteDataRecordNapi::NewPlainTextRecordInstance(napi_env env, const std::string &text, napi_value &instance) +{ + NAPI_CALL_BASE(env, PasteDataRecordNapi::NewInstance(env, instance), false); + PasteDataRecordNapi *obj = nullptr; + napi_status status = napi_unwrap(env, instance, reinterpret_cast(&obj)); + if ((status != napi_ok) || (obj == nullptr)) { + return false; + } + obj->value_ = PasteboardClient::GetInstance()->CreatePlainTextRecord(text); + obj->JSFillInstance(env, instance); + return true; +} + +bool PasteDataRecordNapi::NewPixelMapRecordInstance( + napi_env env, const std::shared_ptr pixelMap, napi_value &instance) +{ + if (pixelMap == nullptr) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "pixelMap is nullptr."); + return false; + } + + NAPI_CALL_BASE(env, PasteDataRecordNapi::NewInstance(env, instance), false); + PasteDataRecordNapi *obj = nullptr; + napi_status status = napi_unwrap(env, instance, reinterpret_cast(&obj)); + if ((status != napi_ok) || (obj == nullptr)) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "unwrap failed."); + return false; + } + obj->value_ = PasteboardClient::GetInstance()->CreatePixelMapRecord(pixelMap); + obj->JSFillInstance(env, instance); + return true; +} + +bool PasteDataRecordNapi::NewUriRecordInstance(napi_env env, const std::string &text, napi_value &instance) +{ + NAPI_CALL_BASE(env, PasteDataRecordNapi::NewInstance(env, instance), false); + PasteDataRecordNapi *obj = nullptr; + napi_status status = napi_unwrap(env, instance, reinterpret_cast(&obj)); + if ((status != napi_ok) || (obj == nullptr)) { + return false; + } + obj->value_ = PasteboardClient::GetInstance()->CreateUriRecord(OHOS::Uri(text)); + obj->JSFillInstance(env, instance); + return true; +} + +bool PasteDataRecordNapi::NewWantRecordInstance( + napi_env env, const std::shared_ptr want, napi_value &instance) +{ + if (!want) { + return false; + } + + NAPI_CALL_BASE(env, PasteDataRecordNapi::NewInstance(env, instance), false); + PasteDataRecordNapi *obj = nullptr; + napi_status status = napi_unwrap(env, instance, reinterpret_cast(&obj)); + if ((status != napi_ok) || (obj == nullptr)) { + return false; + } + obj->value_ = PasteboardClient::GetInstance()->CreateWantRecord(want); + obj->JSFillInstance(env, instance); + return true; +} + +bool PasteDataRecordNapi::NewKvRecordInstance( + napi_env env, const std::string &mimeType, const std::vector &arrayBuffer, napi_value &instance) +{ + NAPI_CALL_BASE(env, PasteDataRecordNapi::NewInstance(env, instance), false); + PasteDataRecordNapi *obj = nullptr; + napi_status status = napi_unwrap(env, instance, reinterpret_cast(&obj)); + if ((status != napi_ok) || (obj == nullptr)) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "unwrap failed"); + return false; + } + obj->value_ = PasteboardClient::GetInstance()->CreateKvRecord(mimeType, arrayBuffer); + obj->JSFillInstance(env, instance); + return true; +} + +void PasteDataRecordNapi::SetNamedPropertyByStr( + napi_env env, napi_value &instance, const char *propName, const char *propValue) +{ + if (propName == nullptr || propValue == nullptr) { + return; + } + napi_value prop = nullptr; + if (napi_create_string_utf8(env, propValue, NAPI_AUTO_LENGTH, &prop) == napi_ok) { + napi_set_named_property(env, instance, propName, prop); + } +} + +napi_value PasteDataRecordNapi::SetNapiKvData(napi_env env, std::shared_ptr customData) +{ + if (customData == nullptr) { + return nullptr; + } + napi_value jsCustomData = nullptr; + napi_create_object(env, &jsCustomData); + auto itemData = customData->GetItemData(); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "size = %{public}d.", static_cast(itemData.size())); + for (auto &item : itemData) { + void *data = nullptr; + napi_value arrayBuffer = nullptr; + size_t len = item.second.size(); + NAPI_CALL(env, napi_create_arraybuffer(env, len, &data, &arrayBuffer)); + if (memcpy_s(data, len, reinterpret_cast(item.second.data()), len) != 0) { + return nullptr; + } + NAPI_CALL(env, napi_set_named_property(env, jsCustomData, item.first.c_str(), arrayBuffer)); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "mimeType = %{public}s.", item.first.c_str()); + } + return jsCustomData; +} + +std::shared_ptr PasteDataRecordNapi::GetNativeKvData(napi_env env, napi_value napiValue) +{ + napi_valuetype valueType = napi_undefined; + NAPI_CALL(env, napi_typeof(env, napiValue, &valueType)); + NAPI_ASSERT(env, valueType == napi_object, "Wrong argument type. Object expected."); + + napi_value mimeTypes = nullptr; + NAPI_CALL(env, napi_get_property_names(env, napiValue, &mimeTypes)); + uint32_t mimeTypesNum = 0; + NAPI_CALL(env, napi_get_array_length(env, mimeTypes, &mimeTypesNum)); + + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "mimeTypesNum = %{public}u", mimeTypesNum); + std::shared_ptr customData = std::make_shared(); + for (uint32_t i = 0; i < mimeTypesNum; i++) { + napi_value mimeTypeNapi = nullptr; + NAPI_CALL(env, napi_get_element(env, mimeTypes, i, &mimeTypeNapi)); + + std::string mimeType; + bool ret = GetValue(env, mimeTypeNapi, mimeType); + if (!ret || (mimeType.size() > MIMETYPE_MAX_SIZE) || mimeType == "") { + return nullptr; + } + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "mimeType = %{public}s,", mimeType.c_str()); + + napi_value napiArrayBuffer = nullptr; + NAPI_CALL(env, napi_get_property(env, napiValue, mimeTypeNapi, &napiArrayBuffer)); + void *data = nullptr; + size_t dataLen; + NAPI_CALL(env, napi_get_arraybuffer_info(env, napiArrayBuffer, &data, &dataLen)); + customData->AddItemData(mimeType, + std::vector(reinterpret_cast(data), reinterpret_cast(data) + dataLen)); + } + return customData; +} + +void PasteDataRecordNapi::JSFillInstance(napi_env env, napi_value &instance) +{ + if (value_ == nullptr) { + return; + } + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_JS_NAPI, "mimeType = %{public}s.", value_->GetMimeType().c_str()); + + auto mimeType = value_->GetMimeType(); + SetNamedPropertyByStr(env, instance, "mimeType", mimeType.c_str()); + + auto plainText = value_->GetPlainText(); + if (plainText != nullptr) { + SetNamedPropertyByStr(env, instance, "plainText", plainText->c_str()); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "fill plainText."); + } + + auto htmlText = value_->GetHtmlText(); + if (htmlText != nullptr) { + SetNamedPropertyByStr(env, instance, "htmlText", htmlText->c_str()); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "fill htmlText."); + } + + auto uri = value_->GetUri(); + if (uri != nullptr) { + SetNamedPropertyByStr(env, instance, "uri", uri->ToString().c_str()); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "fill uri."); + } + + auto want = value_->GetWant(); + if (want != nullptr) { + napi_value jsWant = OHOS::AppExecFwk::WrapWant(env, *want); + napi_set_named_property(env, instance, "want", jsWant); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "fill want."); + } + + auto pixelMap = value_->GetPixelMap(); + if (pixelMap != nullptr) { + napi_value jsPixelMap = OHOS::Media::PixelMapNapi::CreatePixelMap(env, pixelMap); + napi_set_named_property(env, instance, "pixelMap", jsPixelMap); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "fill pixelMap."); + } + + auto customData = value_->GetCustomData(); + if (customData != nullptr) { + napi_value jsCustomData = PasteDataRecordNapi::SetNapiKvData(env, customData); + napi_set_named_property(env, instance, "data", jsCustomData); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "fill data."); + } +} + +napi_value PasteDataRecordNapi::ConvertToText(napi_env env, napi_callback_info info) +{ + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_JS_NAPI, "ConvertToText is called!"); + + struct ExeContext { + std::string text; + PasteDataRecordNapi *obj = nullptr; + }; + auto exeContext = std::make_shared(); + auto input = [exeContext](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status { + // convertToText(callback: AsyncCallback) has 1 args + if (argc > 0 && + !CheckArgsType(env, argv[0], napi_function, "Parameter error. The type of callback must be function.")) { + return napi_invalid_arg; + } + PasteDataRecordNapi *obj = nullptr; + napi_status status = napi_unwrap(env, self, reinterpret_cast(&obj)); + if (status == napi_ok || obj != nullptr) { + exeContext->obj = obj; + } + return napi_ok; + }; + + auto exec = [exeContext](AsyncCall::Context *ctx) { + if ((exeContext->obj != nullptr) && (exeContext->obj->value_ != nullptr)) { + exeContext->text = exeContext->obj->value_->ConvertToText(); + } + }; + auto output = [exeContext](napi_env env, napi_value *result) -> napi_status { + napi_status status = + napi_create_string_utf8(env, (exeContext->text).c_str(), (exeContext->text).length(), result); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "napi_create_string_utf8 status = %{public}d", status); + return status; + }; + + // 0: the AsyncCall at the first position; + AsyncCall asyncCall(env, info, std::make_shared(std::move(input), std::move(output)), 0); + return asyncCall.Call(env, exec); +} + +napi_value PasteDataRecordNapi::ConvertToTextV9(napi_env env, napi_callback_info info) +{ + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_JS_NAPI, "ConvertToTextV9 is called!"); + return ConvertToText(env, info); +} + +napi_value PasteDataRecordNapi::ToPlainText(napi_env env, napi_callback_info info) +{ + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_JS_NAPI, "ToPlainText is called!"); + size_t argc = 1; + napi_value argv[1] = { 0 }; + napi_value thisVar = nullptr; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL)); + NAPI_ASSERT(env, argc >= ARGC_TYPE_SET0, "Wrong number of arguments"); + + PasteDataRecordNapi *obj = nullptr; + napi_status status = napi_unwrap(env, thisVar, reinterpret_cast(&obj)); + if ((status != napi_ok) || (obj == nullptr)) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "Get ToPlainText object failed"); + return nullptr; + } + + std::string str = obj->value_->ConvertToText(); + napi_value result = nullptr; + napi_create_string_utf8(env, str.c_str(), NAPI_AUTO_LENGTH, &result); + return result; +} + +napi_value PasteDataRecordNapi::PasteDataRecordInit(napi_env env, napi_value exports) +{ + napi_property_descriptor properties[] = { + DECLARE_NAPI_FUNCTION("convertToText", ConvertToText), + DECLARE_NAPI_FUNCTION("convertToTextV9", ConvertToTextV9), + DECLARE_NAPI_FUNCTION("toPlainText", ToPlainText) + }; + + napi_status status = napi_ok; + + napi_value constructor; + status = napi_define_class(env, "PasteDataRecord", NAPI_AUTO_LENGTH, New, nullptr, + sizeof(properties) / sizeof(napi_property_descriptor), properties, &constructor); + if (status != napi_ok) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "Failed to define class at PasteDataRecordInit"); + return nullptr; + } + + status = napi_create_reference(env, constructor, 1, &g_pasteDataRecord); + if (status != napi_ok) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "PasteDataRecordInit create reference failed"); + return nullptr; + } + napi_set_named_property(env, exports, "PasteDataRecord", constructor); + return exports; +} + +void PasteDataRecordNapi::Destructor(napi_env env, void *nativeObject, void *finalize_hint) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "Destructor"); + PasteDataRecordNapi *obj = static_cast(nativeObject); + delete obj; +} + +napi_value PasteDataRecordNapi::New(napi_env env, napi_callback_info info) +{ + size_t argc = ARGC_TYPE_SET1; + napi_value argv[1] = { 0 }; + napi_value thisVar = nullptr; + napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr); + + // get native object + PasteDataRecordNapi *obj = new PasteDataRecordNapi(); + obj->env_ = env; + NAPI_CALL(env, napi_wrap(env, thisVar, obj, PasteDataRecordNapi::Destructor, nullptr, nullptr)); + return thisVar; +} + +napi_status PasteDataRecordNapi::NewInstance(napi_env env, napi_value &instance) +{ + napi_status status = napi_invalid_arg; + + napi_value constructor; + status = napi_get_reference_value(env, g_pasteDataRecord, &constructor); + if (status != napi_ok) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "get reference failed"); + return status; + } + + status = napi_new_instance(env, constructor, 0, nullptr, &instance); + if (status != napi_ok) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "new instance failed"); + return status; + } + + return napi_ok; +} +} // namespace MiscServicesNapi +} // namespace OHOS diff --git a/pasteboard/interfaces/kits/napi/src/napi_systempasteboard.cpp b/pasteboard/interfaces/kits/napi/src/napi_systempasteboard.cpp new file mode 100644 index 00000000..3e719f79 --- /dev/null +++ b/pasteboard/interfaces/kits/napi/src/napi_systempasteboard.cpp @@ -0,0 +1,767 @@ +/* + * Copyright (C) 2021-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include + +#include "common/block_object.h" +#include "napi_common_want.h" +#include "pasteboard_common.h" +#include "pasteboard_error.h" +#include "pasteboard_hilog.h" +#include "pasteboard_js_err.h" +#include "systempasteboard_napi.h" +using namespace OHOS::MiscServices; +using namespace OHOS::Media; + +namespace OHOS { +namespace MiscServicesNapi { +static thread_local napi_ref g_systemPasteboard = nullptr; +static thread_local napi_ref g_systemPasteboard_instance = nullptr; +thread_local std::map> SystemPasteboardNapi::observers_; +constexpr int ARGC_TYPE_SET1 = 1; +constexpr size_t MAX_ARGS = 6; +constexpr size_t SYNC_TIMEOUT = 5; +const std::string STRING_UPDATE = "update"; +PasteboardObserverInstance::PasteboardObserverInstance(const napi_env &env, const napi_ref &ref) : env_(env), ref_(ref) +{ + stub_ = new (std::nothrow) PasteboardObserverInstance::PasteboardObserverImpl(); +} + +PasteboardObserverInstance::~PasteboardObserverInstance() +{ + napi_delete_reference(env_, ref_); +} + +sptr PasteboardObserverInstance::GetStub() +{ + return stub_; +} + +void UvQueueWorkOnPasteboardChanged(uv_work_t *work, int status) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "UvQueueWorkOnPasteboardChanged start"); + if (work == nullptr) { + return; + } + PasteboardDataWorker *pasteboardDataWorker = (PasteboardDataWorker *)work->data; + if (pasteboardDataWorker == nullptr || pasteboardDataWorker->observer == nullptr) { + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "pasteboardDataWorker or ref is null"); + delete work; + work = nullptr; + return; + } + + auto env = pasteboardDataWorker->observer->GetEnv(); + auto ref = pasteboardDataWorker->observer->GetRef(); + + napi_handle_scope scope = nullptr; + napi_open_handle_scope(env, &scope); + if (scope == nullptr) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "scope null"); + return; + } + napi_value undefined = nullptr; + napi_get_undefined(env, &undefined); + + napi_value callback = nullptr; + napi_value resultOut = nullptr; + napi_get_reference_value(env, ref, &callback); + napi_value result = NapiGetNull(env); + napi_call_function(env, undefined, callback, 0, &result, &resultOut); + + napi_close_handle_scope(env, scope); + delete pasteboardDataWorker; + pasteboardDataWorker = nullptr; + delete work; +} + +void PasteboardObserverInstance::OnPasteboardChanged() +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "OnPasteboardChanged is called!"); + uv_loop_s *loop = nullptr; + napi_get_uv_event_loop(env_, &loop); + if (loop == nullptr) { + PASTEBOARD_HILOGW(PASTEBOARD_MODULE_JS_NAPI, "loop instance is nullptr"); + return; + } + + uv_work_t *work = new (std::nothrow) uv_work_t; + if (work == nullptr) { + PASTEBOARD_HILOGW(PASTEBOARD_MODULE_JS_NAPI, "work is null"); + return; + } + PasteboardDataWorker *pasteboardDataWorker = new (std::nothrow) PasteboardDataWorker(); + if (pasteboardDataWorker == nullptr) { + PASTEBOARD_HILOGW(PASTEBOARD_MODULE_JS_NAPI, "pasteboardDataWorker is null"); + delete work; + work = nullptr; + return; + } + pasteboardDataWorker->observer = shared_from_this(); + + work->data = (void *)pasteboardDataWorker; + + int ret = uv_queue_work( + loop, work, [](uv_work_t *work) {}, UvQueueWorkOnPasteboardChanged); + if (ret != 0) { + delete pasteboardDataWorker; + pasteboardDataWorker = nullptr; + delete work; + work = nullptr; + } + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "OnPasteboardChanged end"); +} + +bool SystemPasteboardNapi::CheckAgrsOfOnAndOff(napi_env env, bool checkArgsCount, napi_value *argv, size_t argc) +{ + if (!CheckExpression( + env, checkArgsCount, JSErrorCode::INVALID_PARAMETERS, "Parameter error. Wrong number of arguments.") || + !CheckArgsType(env, argv[0], napi_string, "Parameter error. The type of mimeType must be string.")) { + return false; + } + std::string mimeType; + bool ret = GetValue(env, argv[0], mimeType); + if (!ret) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "GetValue failed"); + return false; + } + if (!CheckExpression(env, mimeType == STRING_UPDATE, JSErrorCode::INVALID_PARAMETERS, + "Parameter error. The value of type must be update")) { + return false; + } + return true; +} + +napi_value SystemPasteboardNapi::On(napi_env env, napi_callback_info info) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "SystemPasteboardNapi on() is called!"); + size_t argc = MAX_ARGS; + napi_value argv[MAX_ARGS] = { 0 }; + napi_value thisVar = 0; + void *data = nullptr; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, &data)); + // on(type: 'update', callback: () => void) has 2 args + if (!CheckAgrsOfOnAndOff(env, argc >= 2, argv, argc) || + !CheckArgsType(env, argv[1], napi_function, "Parameter error. The type of callback must be function.")) { + return nullptr; + } + + napi_value result = nullptr; + napi_get_undefined(env, &result); + auto observer = GetObserver(env, argv[1]); + if (observer != nullptr) { + PASTEBOARD_HILOGW(PASTEBOARD_MODULE_JS_NAPI, "observer exist."); + return result; + } + napi_ref ref = nullptr; + napi_create_reference(env, argv[1], 1, &ref); + observer = std::make_shared(env, ref); + observer->GetStub()->SetObserverWrapper(observer); + PasteboardClient::GetInstance()->AddPasteboardChangedObserver(observer->GetStub()); + observers_[ref] = observer; + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "SystemPasteboardNapi on() is end!"); + return result; +} + +napi_value SystemPasteboardNapi::Off(napi_env env, napi_callback_info info) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "SystemPasteboardNapi off () is called!"); + size_t argc = MAX_ARGS; + napi_value argv[MAX_ARGS] = { 0 }; + napi_value thisVar = 0; + void *data = nullptr; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, &data)); + // off(type: 'update', callback?: () => void) has at least 1 arg + if (!CheckAgrsOfOnAndOff(env, argc >= 1, argv, argc)) { + return nullptr; + } + + std::shared_ptr observer = nullptr; + // 1: is the observer parameter + if (argc > 1) { + if (!CheckArgsType(env, argv[1], napi_function, "Parameter error. The type of callback must be function.")) { + return nullptr; + } + observer = GetObserver(env, argv[1]); + } + + DeleteObserver(observer); + napi_value result = nullptr; + napi_get_undefined(env, &result); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "SystemPasteboardNapi off () is called!"); + return result; +} + +napi_value SystemPasteboardNapi::Clear(napi_env env, napi_callback_info info) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "Clear is called!"); + auto context = std::make_shared(); + auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status { + // clear has 0 or 1 args + if (argc > 0 && + !CheckArgsType(env, argv[0], napi_function, "Parameter error. The type of callback must be function.")) { + return napi_invalid_arg; + } + return napi_ok; + }; + auto exec = [context](AsyncCall::Context *ctx) { + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "exec Clear"); + PasteboardClient::GetInstance()->Clear(); + }; + context->SetAction(std::move(input)); + // 0: the AsyncCall at the first position; + AsyncCall asyncCall(env, info, context, 0); + return asyncCall.Call(env, exec); +} + +napi_value SystemPasteboardNapi::ClearData(napi_env env, napi_callback_info info) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "ClearData is called!"); + return Clear(env, info); +} + +napi_value SystemPasteboardNapi::HasPasteData(napi_env env, napi_callback_info info) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "HasPasteData is called!"); + auto context = std::make_shared(); + auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status { + // hasPasteData has 0 or 1 args + if (argc > 0 && + !CheckArgsType(env, argv[0], napi_function, "Parameter error. The type of callback must be function.")) { + return napi_invalid_arg; + } + return napi_ok; + }; + auto output = [context](napi_env env, napi_value *result) -> napi_status { + napi_status status = napi_get_boolean(env, context->hasPasteData, result); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "napi_get_boolean status = %{public}d", status); + return status; + }; + auto exec = [context](AsyncCall::Context *ctx) { + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "exec HasPasteData"); + context->hasPasteData = PasteboardClient::GetInstance()->HasPasteData(); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "HasPasteData result = %{public}d", context->hasPasteData); + context->status = napi_ok; + }; + context->SetAction(std::move(input), std::move(output)); + // 0: the AsyncCall at the first position; + AsyncCall asyncCall(env, info, context, 0); + return asyncCall.Call(env, exec); +} + +napi_value SystemPasteboardNapi::HasData(napi_env env, napi_callback_info info) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "HasData is called!"); + return HasPasteData(env, info); +} + +void SystemPasteboardNapi::GetDataCommon(std::shared_ptr &context) +{ + auto input = [](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status { + // 1: GetPasteData has 0 or 1 args + if (argc > 0 && + !CheckArgsType(env, argv[0], napi_function, "Parameter error. The type of callback must be function.")) { + return napi_invalid_arg; + } + return napi_ok; + }; + + auto output = [context](napi_env env, napi_value *result) -> napi_status { + napi_value instance = nullptr; + PasteDataNapi::NewInstance(env, instance); + PasteDataNapi *obj = nullptr; + napi_status ret = napi_unwrap(env, instance, reinterpret_cast(&obj)); + if ((ret == napi_ok) || (obj != nullptr)) { + obj->value_ = context->pasteData; + } else { + return napi_generic_failure; + } + *result = instance; + return napi_ok; + }; + context->SetAction(std::move(input), std::move(output)); +} + +napi_value SystemPasteboardNapi::GetPasteData(napi_env env, napi_callback_info info) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "GetPasteData is called!"); + + auto context = std::make_shared(); + context->pasteData = std::make_shared(); + GetDataCommon(context); + + auto exec = [context](AsyncCall::Context *ctx) { + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "GetPasteData Begin"); + PasteboardClient::GetInstance()->GetPasteData(*context->pasteData); + context->status = napi_ok; + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "GetPasteData End"); + }; + + // 0: the AsyncCall at the first position; + AsyncCall asyncCall(env, info, context, 0); + return asyncCall.Call(env, exec); +} + +napi_value SystemPasteboardNapi::GetData(napi_env env, napi_callback_info info) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "GetData is called!"); + + auto context = std::make_shared(); + context->pasteData = std::make_shared(); + GetDataCommon(context); + + auto exec = [context](AsyncCall::Context *ctx) { + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "GetData Begin"); + int32_t ret = PasteboardClient::GetInstance()->GetPasteData(*context->pasteData); + if (ret == static_cast(PasteboardError::E_IS_BEGING_PROCESSED)) { + context->SetErrInfo(ret, "Another getData is being processed"); + } else { + context->status = napi_ok; + } + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "GetData End"); + }; + // 0: the AsyncCall at the first position; + AsyncCall asyncCall(env, info, context, 0); + return asyncCall.Call(env, exec); +} + +void SystemPasteboardNapi::SetDataCommon(std::shared_ptr &context) +{ + auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status { + // setData has 1 or 2 args + if (!CheckExpression( + env, argc > 0, JSErrorCode::INVALID_PARAMETERS, "Parameter error. Wrong number of arguments.") || + !CheckExpression(env, PasteDataNapi::IsPasteData(env, argv[0]), JSErrorCode::INVALID_PARAMETERS, + "Parameter error. The Type of data must be pasteData.")) { + return napi_invalid_arg; + } + if (argc > 1 && + !CheckArgsType(env, argv[1], napi_function, "Parameter error. The type of callback must be function.")) { + return napi_invalid_arg; + } + PasteDataNapi *pasteData = nullptr; + napi_unwrap(env, argv[0], reinterpret_cast(&pasteData)); + if (pasteData != nullptr) { + context->obj = pasteData->value_; + } + return napi_ok; + }; + context->SetAction(std::move(input)); +} + +napi_value SystemPasteboardNapi::SetPasteData(napi_env env, napi_callback_info info) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "SetPasteData is called!"); + auto context = std::make_shared(); + SetDataCommon(context); + + auto exec = [context](AsyncCall::Context *ctx) { + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "exec SetPasteData"); + if (context->obj != nullptr) { + PasteboardClient::GetInstance()->SetPasteData(*(context->obj)); + context->obj = nullptr; + } + context->status = napi_ok; + }; + // 1: the AsyncCall at the second position + AsyncCall asyncCall(env, info, context, 1); + return asyncCall.Call(env, exec); +} + +napi_value SystemPasteboardNapi::SetData(napi_env env, napi_callback_info info) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "SetData is called!"); + auto context = std::make_shared(); + SetDataCommon(context); + + auto exec = [context](AsyncCall::Context *ctx) { + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "exec SetPasteData"); + int32_t ret = static_cast(PasteboardError::E_ERROR); + if (context->obj != nullptr) { + ret = PasteboardClient::GetInstance()->SetPasteData(*(context->obj)); + context->obj = nullptr; + } + if (ret == static_cast(PasteboardError::E_OK)) { + context->status = napi_ok; + } else if (ret == static_cast(PasteboardError::E_COPY_FORBIDDEN)) { + context->SetErrInfo(ret, "The system prohibits copying"); + } else if (ret == static_cast(PasteboardError::E_IS_BEGING_PROCESSED)) { + context->SetErrInfo(ret, "Another setData is being processed"); + } + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "exec context->status[%{public}d]", context->status); + }; + // 1: the AsyncCall at the second position + AsyncCall asyncCall(env, info, context, 1); + return asyncCall.Call(env, exec); +} + +napi_value SystemPasteboardNapi::IsRemoteData(napi_env env, napi_callback_info info) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "SystemPasteboardNapi IsRemoteData() is called!"); + auto block = std::make_shared>>(SYNC_TIMEOUT); + std::thread thread([block]() { + auto ret = PasteboardClient::GetInstance()->IsRemoteData(); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "value=%{public}d", ret); + std::shared_ptr value = std::make_shared(static_cast(ret)); + block->SetValue(value); + }); + thread.detach(); + auto value = block->GetValue(); + if (!CheckExpression(env, value != nullptr, JSErrorCode::REQUEST_TIME_OUT, "Request time out.")) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "time out, IsRemoteData failed."); + return nullptr; + } + napi_value result = nullptr; + napi_get_boolean(env, *value, &result); + return result; +} + +napi_value SystemPasteboardNapi::GetDataSource(napi_env env, napi_callback_info info) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "SystemPasteboardNapi GetDataSource() is called!"); + std::string bundleName; + auto block = std::make_shared>>(SYNC_TIMEOUT); + std::thread thread([block, &bundleName]() mutable { + auto ret = PasteboardClient::GetInstance()->GetDataSource(bundleName); + std::shared_ptr value = std::make_shared(ret); + block->SetValue(value); + }); + thread.detach(); + auto value = block->GetValue(); + if (!CheckExpression(env, value != nullptr, JSErrorCode::REQUEST_TIME_OUT, "Request time out.")) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "time out, GetDataSource failed."); + return nullptr; + } + + if (*value != static_cast(PasteboardError::E_OK)) { + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "GetDataSource, failed, ret = %{public}d", *value); + return nullptr; + } + napi_value result = nullptr; + napi_create_string_utf8(env, bundleName.c_str(), NAPI_AUTO_LENGTH, &result); + return result; +} + +napi_value SystemPasteboardNapi::HasDataType(napi_env env, napi_callback_info info) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "SystemPasteboardNapi HasDataType() is called!"); + size_t argc = 1; + napi_value argv[1] = { 0 }; + napi_value thisVar = nullptr; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL)); + if ((!CheckExpression(env, argc >= ARGC_TYPE_SET1, JSErrorCode::INVALID_PARAMETERS, + "Parameter error. Wrong number of arguments.")) || + (!CheckArgsType(env, argv[0], napi_string, "Parameter error. The type of mimeType must be string."))) { + return nullptr; + } + + std::string mimeType; + if (!GetValue(env, argv[0], mimeType)) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "Failed to GetValue!"); + return nullptr; + } + auto block = std::make_shared>>(SYNC_TIMEOUT); + std::thread thread([block, mimeType]() { + auto ret = PasteboardClient::GetInstance()->HasDataType(mimeType); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "ret = %{public}d", ret); + std::shared_ptr value = std::make_shared(static_cast(ret)); + block->SetValue(value); + }); + thread.detach(); + auto value = block->GetValue(); + if (!CheckExpression(env, value != nullptr, JSErrorCode::REQUEST_TIME_OUT, "Request time out.")) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "time out, HasDataType failed."); + return nullptr; + } + napi_value result = nullptr; + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "value = %{public}d", *value); + napi_get_boolean(env, *value, &result); + return result; +} + +napi_value SystemPasteboardNapi::ClearDataSync(napi_env env, napi_callback_info info) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "SystemPasteboardNapi ClearDataSync() is called!"); + auto block = std::make_shared>>(SYNC_TIMEOUT); + std::thread thread([block]() { + PasteboardClient::GetInstance()->Clear(); + std::shared_ptr value = std::make_shared(0); + block->SetValue(value); + }); + thread.detach(); + auto value = block->GetValue(); + if (!CheckExpression(env, value != nullptr, JSErrorCode::REQUEST_TIME_OUT, "Request time out.")) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "time out, ClearDataSync failed."); + } + return nullptr; +} + +napi_value SystemPasteboardNapi::GetDataSync(napi_env env, napi_callback_info info) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "SystemPasteboardNapi GetDataSync() is called!"); + napi_value instance = nullptr; + NAPI_CALL(env, PasteDataNapi::NewInstance(env, instance)); + PasteDataNapi *obj = nullptr; + napi_status status = napi_unwrap(env, instance, reinterpret_cast(&obj)); + if ((status != napi_ok) || (obj == nullptr)) { + return nullptr; + } + auto block = std::make_shared>>(SYNC_TIMEOUT); + std::thread thread([block, &obj]() mutable { + auto ret = PasteboardClient::GetInstance()->GetPasteData(*(obj->value_)); + std::shared_ptr value = std::make_shared(static_cast(ret)); + block->SetValue(value); + }); + thread.detach(); + auto value = block->GetValue(); + if (!CheckExpression(env, value != nullptr, JSErrorCode::REQUEST_TIME_OUT, "request time out.")) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "time out, GetDataSync failed."); + return nullptr; + } + + if (*value != static_cast(PasteboardError::E_OK)) { + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "operate invalid, GetDataSync failed"); + return nullptr; + } + + return instance; +} + +napi_value SystemPasteboardNapi::SetDataSync(napi_env env, napi_callback_info info) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "SystemPasteboardNapi SetDataSync() is called!"); + size_t argc = 1; + napi_value argv[1] = { 0 }; + napi_value thisVar = nullptr; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL)); + if (!CheckExpression(env, argc > 0, JSErrorCode::INVALID_PARAMETERS, + "Parameter error. Wrong number of arguments.") || + !CheckExpression(env, PasteDataNapi::IsPasteData(env, argv[0]), JSErrorCode::INVALID_PARAMETERS, + "Parameter error. The Type of data must be pasteData.")) { + return nullptr; + } + + PasteDataNapi *pasteData = nullptr; + napi_unwrap(env, argv[0], reinterpret_cast(&pasteData)); + if (pasteData == nullptr) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "Failed to GetValue!"); + return nullptr; + } + auto block = std::make_shared>>(SYNC_TIMEOUT); + std::thread thread([block, pasteData]() { + auto ret = PasteboardClient::GetInstance()->SetPasteData(*(pasteData->value_)); + std::shared_ptr value = std::make_shared(static_cast(ret)); + block->SetValue(value); + }); + thread.detach(); + auto value = block->GetValue(); + if (!CheckExpression(env, value != nullptr, JSErrorCode::REQUEST_TIME_OUT, "request time out.")) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "time out, SetDataSync failed."); + return nullptr; + } + + if (*value != static_cast(PasteboardError::E_OK)) { + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "operate invalid, SetDataSync failed"); + return nullptr; + } + return nullptr; +} + +napi_value SystemPasteboardNapi::HasDataSync(napi_env env, napi_callback_info info) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "SystemPasteboardNapi HasDataSync() is called!"); + auto block = std::make_shared>>(SYNC_TIMEOUT); + std::thread thread([block]() { + auto ret = PasteboardClient::GetInstance()->HasPasteData(); + std::shared_ptr value = std::make_shared(static_cast(ret)); + block->SetValue(value); + }); + thread.detach(); + auto value = block->GetValue(); + if (!CheckExpression(env, value != nullptr, JSErrorCode::REQUEST_TIME_OUT, "request time out.")) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "time out, HasDataSync failed."); + return nullptr; + } + napi_value result = nullptr; + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "value=%{public}d", *value); + napi_get_boolean(env, *value, &result); + return result; +} + +napi_value SystemPasteboardNapi::SystemPasteboardInit(napi_env env, napi_value exports) +{ + napi_status status = napi_ok; + napi_property_descriptor descriptors[] = { + DECLARE_NAPI_FUNCTION("on", On), + DECLARE_NAPI_FUNCTION("off", Off), + DECLARE_NAPI_FUNCTION("clear", Clear), + DECLARE_NAPI_FUNCTION("getPasteData", GetPasteData), + DECLARE_NAPI_FUNCTION("hasPasteData", HasPasteData), + DECLARE_NAPI_FUNCTION("setPasteData", SetPasteData), + DECLARE_NAPI_FUNCTION("clearData", ClearData), + DECLARE_NAPI_FUNCTION("getData", GetData), + DECLARE_NAPI_FUNCTION("hasData", HasData), + DECLARE_NAPI_FUNCTION("setData", SetData), + DECLARE_NAPI_FUNCTION("isRemoteData", IsRemoteData), + DECLARE_NAPI_FUNCTION("getDataSource", GetDataSource), + DECLARE_NAPI_FUNCTION("hasDataType", HasDataType), + DECLARE_NAPI_FUNCTION("clearDataSync", ClearDataSync), + DECLARE_NAPI_FUNCTION("getDataSync", GetDataSync), + DECLARE_NAPI_FUNCTION("hasDataSync", HasDataSync), + DECLARE_NAPI_FUNCTION("setDataSync", SetDataSync), + }; + napi_value constructor; + napi_define_class(env, "SystemPasteboard", NAPI_AUTO_LENGTH, New, nullptr, + sizeof(descriptors) / sizeof(napi_property_descriptor), descriptors, &constructor); + if (status != napi_ok) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "Failed to define class at SystemPasteboardInit"); + return nullptr; + } + napi_create_reference(env, constructor, 1, &g_systemPasteboard); + status = napi_set_named_property(env, exports, "SystemPasteboard", constructor); + if (status != napi_ok) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "Set property failed when SystemPasteboardInit"); + return nullptr; + } + return exports; +} + +SystemPasteboardNapi::SystemPasteboardNapi() : env_(nullptr) +{ + value_ = std::make_shared(); +} + +SystemPasteboardNapi::~SystemPasteboardNapi() +{ +} + +void SystemPasteboardNapi::Destructor(napi_env env, void *nativeObject, void *finalize_hint) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "Destructor"); + SystemPasteboardNapi *obj = static_cast(nativeObject); + delete obj; +} + +napi_value SystemPasteboardNapi::New(napi_env env, napi_callback_info info) +{ + size_t argc = MAX_ARGS; + napi_value argv[MAX_ARGS] = { 0 }; + napi_value thisVar = nullptr; + napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "proc."); + // get native object + SystemPasteboardNapi *obj = new (std::nothrow) SystemPasteboardNapi(); + if (!obj) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "New obj is null"); + return nullptr; + } + obj->env_ = env; + NAPI_CALL(env, napi_wrap(env, thisVar, obj, SystemPasteboardNapi::Destructor, + nullptr, // finalize_hint + nullptr)); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "end."); + return thisVar; +} + +napi_status SystemPasteboardNapi::NewInstance(napi_env env, napi_value &instance) +{ + napi_status status; + if (g_systemPasteboard_instance != nullptr) { + status = napi_get_reference_value(env, g_systemPasteboard_instance, &instance); + if (status != napi_ok) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "get instance failed"); + return status; + } + return napi_ok; + } + + napi_value constructor; + status = napi_get_reference_value(env, g_systemPasteboard, &constructor); + if (status != napi_ok) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "get reference failed"); + return status; + } + + status = napi_new_instance(env, constructor, 0, nullptr, &instance); + if (status != napi_ok) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "new instance failed"); + return status; + } + napi_create_reference(env, instance, 1, &g_systemPasteboard_instance); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "new instance ok"); + + return napi_ok; +} + +std::shared_ptr SystemPasteboardNapi::GetObserver(napi_env env, napi_value observer) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "GetObserver start"); + for (auto &[refKey, observerValue] : observers_) { + napi_value callback = nullptr; + napi_get_reference_value(env, refKey, &callback); + bool isEqual = false; + napi_strict_equals(env, observer, callback, &isEqual); + if (isEqual) { + return observerValue; + } + } + return nullptr; +} + +void SystemPasteboardNapi::DeleteObserver(const std::shared_ptr &observer) +{ + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_JS_NAPI, "observer == null: %{public}d, size: %{public}zu", + observer == nullptr, observers_.size()); + std::vector> observers; + { + for (auto it = observers_.begin(); it != observers_.end();) { + if (it->second == observer) { + observers.push_back(observer); + observers_.erase(it++); + break; + } + if (observer == nullptr) { + observers.push_back(it->second); + observers_.erase(it++); + } else { + it++; + } + } + } + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "delete observer size: %{public}zu", observers.size()); + for (auto &delObserver : observers) { + PasteboardClient::GetInstance()->RemovePasteboardChangedObserver(delObserver->GetStub()); + } +} + +void PasteboardObserverInstance::PasteboardObserverImpl::OnPasteboardChanged() +{ + std::shared_ptr observerInstance(wrapper_.lock()); + if (observerInstance == nullptr) { + PASTEBOARD_HILOGW(PASTEBOARD_MODULE_JS_NAPI, "expired callback"); + return; + } + observerInstance->OnPasteboardChanged(); +} + +void PasteboardObserverInstance::PasteboardObserverImpl::SetObserverWrapper( + const std::shared_ptr &observerInstance) +{ + wrapper_ = observerInstance; +} +} // namespace MiscServicesNapi +} // namespace OHOS \ No newline at end of file diff --git a/pasteboard/interfaces/kits/napi/src/pasteboard_common.cpp b/pasteboard/interfaces/kits/napi/src/pasteboard_common.cpp new file mode 100644 index 00000000..f064b11d --- /dev/null +++ b/pasteboard/interfaces/kits/napi/src/pasteboard_common.cpp @@ -0,0 +1,164 @@ +/* + * Copyright (C) 2021-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "pasteboard_common.h" + +#include "napi_common_want.h" +#include "paste_data_record.h" +#include "pasteboard_hilog.h" +#include "pasteboard_js_err.h" +#include "pixel_map_napi.h" + +namespace OHOS { +namespace MiscServicesNapi { +using namespace OHOS::MiscServices; +const size_t ARGC_TYPE_SET2 = 2; +constexpr size_t STR_TAIL_LENGTH = 1; +constexpr int32_t MIMETYPE_MAX_SIZE = 1024; + +napi_value GetCallbackErrorValue(napi_env env, int32_t errorCode) +{ + napi_value result = nullptr; + napi_value eCode = nullptr; + NAPI_CALL(env, napi_create_int32(env, errorCode, &eCode)); + NAPI_CALL(env, napi_create_object(env, &result)); + NAPI_CALL(env, napi_set_named_property(env, result, "code", eCode)); + return result; +} + +void SetCallback(const napi_env &env, const napi_ref &callbackIn, const napi_value *results) +{ + if (results == nullptr) { + return; + } + napi_value callback = nullptr; + napi_value resultout = nullptr; + napi_get_reference_value(env, callbackIn, &callback); + napi_call_function(env, nullptr, callback, ARGC_TYPE_SET2, results, &resultout); +} + +napi_value NapiGetNull(napi_env env) +{ + napi_value result = nullptr; + napi_get_null(env, &result); + return result; +} + +napi_value CreateNapiNumber(napi_env env, int32_t num) +{ + napi_value value = nullptr; + napi_create_int32(env, num, &value); + return value; +} + +napi_value CreateNapiString(napi_env env, std::string str) +{ + napi_value value = nullptr; + napi_create_string_utf8(env, str.c_str(), NAPI_AUTO_LENGTH, &value); + return value; +} + +/* napi_value <-> std::string */ +bool GetValue(napi_env env, napi_value in, std::string &out) +{ + napi_valuetype type = napi_undefined; + NAPI_CALL_BASE(env, napi_typeof(env, in, &type), false); + NAPI_ASSERT_BASE(env, type == napi_string, "Wrong argument type. String expected.", false); + + size_t len = 0; + NAPI_CALL_BASE(env, napi_get_value_string_utf8(env, in, nullptr, 0, &len), false); + if (len < 0) { + return false; + } + + size_t length = 0; + out.resize(len + STR_TAIL_LENGTH, 0); + NAPI_CALL_BASE(env, napi_get_value_string_utf8(env, in, out.data(), len + STR_TAIL_LENGTH, &length), false); + out.resize(len); + + return true; +} + +bool CheckArgsType(napi_env env, napi_value in, napi_valuetype expectedType, const char *message) +{ + napi_valuetype type = napi_undefined; + NAPI_CALL_BASE(env, napi_typeof(env, in, &type), false); + int32_t errCode = static_cast(JSErrorCode::INVALID_PARAMETERS); + if (type != expectedType) { + napi_throw_error(env, std::to_string(errCode).c_str(), message); + return false; + } + return true; +} + +bool CheckExpression(napi_env env, bool flag, MiscServices::JSErrorCode errCode, const char *message) +{ + if (!flag) { + NAPI_CALL_BASE( + env, napi_throw_error(env, std::to_string(static_cast(errCode)).c_str(), message), false); + return false; + } + return true; +} + +// Check Parameters of CreateData, CreateRecord and AddRecord +bool CheckArgs(napi_env env, napi_value *argv, size_t argc, std::string &mimeType) +{ + // 2: CreateRecord, CreateRecord and AddRecord has 2 args. + if (!CheckExpression(env, argc >= ARGC_TYPE_SET2, JSErrorCode::INVALID_PARAMETERS, + "Parameter error. Wrong number of arguments.") || + !CheckArgsType(env, argv[0], napi_string, "Parameter error. The type of mimeType must be string.")) { + return false; + } + + bool ret = GetValue(env, argv[0], mimeType); + if (!ret) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "GetValue failed"); + return false; + } + if (!CheckExpression( + env, mimeType != "", JSErrorCode::INVALID_PARAMETERS, "Parameter error. mimeType cannot be empty.") || + !CheckExpression(env, mimeType.size() <= MIMETYPE_MAX_SIZE, JSErrorCode::INVALID_PARAMETERS, + "Parameter error. The length of mimeType cannot be greater than 1024 bytes.")) { + return false; + } + const char *message = "Parameter error. The value does not match mimeType correctly."; + + if (mimeType == MIMETYPE_TEXT_URI || mimeType == MIMETYPE_TEXT_PLAIN || mimeType == MIMETYPE_TEXT_HTML) { + if (!CheckArgsType(env, argv[1], napi_string, message)) { + return false; + } + } else if (mimeType == MIMETYPE_PIXELMAP) { + if (!CheckExpression(env, Media::PixelMapNapi::GetPixelMap(env, argv[1]) != nullptr, + JSErrorCode::INVALID_PARAMETERS, message)) { + return false; + } + } else if (mimeType == MIMETYPE_TEXT_WANT) { + AAFwk::Want want; + ret = OHOS::AppExecFwk::UnwrapWant(env, argv[1], want); + if (!CheckExpression(env, ret, JSErrorCode::INVALID_PARAMETERS, message)) { + return false; + } + } else { + bool isArrayBuffer = false; + NAPI_CALL_BASE(env, napi_is_arraybuffer(env, argv[1], &isArrayBuffer), false); + if (!CheckExpression(env, isArrayBuffer, JSErrorCode::INVALID_PARAMETERS, message)) { + return false; + } + } + return true; +} + +} // namespace MiscServicesNapi +} // namespace OHOS \ No newline at end of file diff --git a/pasteboard/interfaces/kits/napi/test/unittest/config.json b/pasteboard/interfaces/kits/napi/test/unittest/config.json new file mode 100644 index 00000000..7c8e142f --- /dev/null +++ b/pasteboard/interfaces/kits/napi/test/unittest/config.json @@ -0,0 +1,64 @@ +{ + "app": { + "bundleName": "ohos.acts.distributeddatamgr.pasteboard", + "vendor": "acts", + "version": { + "code": 1000000, + "name": "1.0.0" + }, + "apiVersion": { + "compatible": 4, + "target": 5 + } + }, + "deviceConfig": {}, + "module": { + "package": "ohos.acts.distributeddatamgr.pasteboard", + "name": ".MyApplication", + "deviceType": [ + "tablet", + "default" + ], + "distro": { + "deliveryWithInstall": true, + "moduleName": "entry", + "moduleType": "entry" + }, + "reqPermissions": [ + + ], + "abilities": [ + { + "visible": true, + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "action.system.home" + ] + } + ], + "name": "ohos.acts.distributeddatamgr.pasteboard.MainAbility", + "icon": "$media:icon", + "description": "$string:mainability_description", + "label": "$string:app_name", + "type": "page", + "launchType": "standard" + } + ], + "js": [ + { + "pages": [ + "pages/index/index" + ], + "name": "default", + "window": { + "designWidth": 720, + "autoDesignWidth": false + } + } + ] + } +} diff --git a/pasteboard/interfaces/kits/napi/test/unittest/openharmony_sx.p7b b/pasteboard/interfaces/kits/napi/test/unittest/openharmony_sx.p7b new file mode 100644 index 0000000000000000000000000000000000000000..53f5f5a3b47fb9c6ba0ae1bd13f0f54192087af3 GIT binary patch literal 3460 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 { + console.info('get paste data success'); + expect(data.getRecordCount()).assertEqual(3); + expect(data.getRecordAt(0).mimeType).assertEqual('xy2'); + expect(data.getRecordAt(1).mimeType).assertEqual('x'.repeat(1024)); + expect(data.getRecordAt(2).mimeType).assertEqual('xy'); + done(); + }); + }); + + /** + * @tc.name pasteboard_exception_test3 + * @tc.desc 自定义数据异常测试 + * @tc.type Function + * @tc.require AR000HEECB + */ + it('pasteboard_exception_test3', 0, async function (done) { + console.info('pasteboard_exception_test1 start'); + const systemPasteboard = pasteboard.getSystemPasteboard(); + await systemPasteboard.clearData(); + console.info('systemPasteboard clear data success'); + let pasteData = undefined; + let pasteRecord = undefined; + + // test createData + let dataHtml = new ArrayBuffer(256); + try { + pasteData = pasteboard.createData('x'.repeat(1025), dataHtml); + expect(true === false).assertTrue(); + } catch (error) { + console.info(error.code); + console.info(error.message); + } + + expect(pasteData).assertEqual(undefined); + pasteData = pasteboard.createData('x'.repeat(1024), dataHtml); + expect(pasteData != undefined).assertTrue(); + + // test addRecord + try { + pasteData.addRecord('x'.repeat(1025), dataHtml); + expect(true === false).assertTrue(); + } catch (error) { + console.info(error.code); + console.info(error.message); + } + expect(pasteData.getRecordCount()).assertEqual(1); + pasteData.addRecord('x'.repeat(1024), dataHtml); + expect(pasteData.getRecordCount()).assertEqual(2); + + let addHtml = new ArrayBuffer(128); + try { + pasteData.addRecord('x'.repeat(1025), addHtml); + expect(true === false).assertTrue(); + } catch (error) { + console.info(error.code); + console.info(error.message); + } + expect(pasteData.getRecordCount()).assertEqual(2); + pasteData.addRecord('x'.repeat(1024), addHtml); + expect(pasteData.getRecordCount()).assertEqual(3); + + let recordHtml = new ArrayBuffer(64); + try { + pasteRecord = pasteboard.createRecord('x'.repeat(1025), recordHtml); + expect(true === false).assertTrue(); + } catch (error) { + console.info(error.code); + console.info(error.message); + } + expect(pasteRecord).assertEqual(undefined); + pasteRecord = pasteboard.createRecord('x'.repeat(1024), recordHtml); + expect(pasteRecord != undefined).assertTrue(); + pasteData.addRecord(pasteRecord); + expect(pasteData.getRecordCount()).assertEqual(4); + await systemPasteboard.setPasteData(pasteData); + console.info('set pastedata success'); + const res = await systemPasteboard.hasPasteData(); + console.info('Check pastedata has data success, result: ' + res); + expect(res).assertTrue(); + systemPasteboard.getPasteData().then((data) => { + console.info('get paste data success'); + expect(data.getRecordCount()).assertEqual(4); + done(); + }); + }); + + /** + * @tc.name pasteboard_exception_test4 + * @tc.desc 一个record中多个数据类型:get primary html、pixelMap、want、text、uri + * @tc.type Function + * @tc.require AR000HEECB + */ + it('pasteboard_exception_test4', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + await systemPasteboard.clearData(); + const dataHtml = new ArrayBuffer(256); + const htmlText = 'Hello!'; + const uriText = 'https://www.baidu.com/'; + const wantText = { + bundleName: 'com.example.myapplication3', + abilityName: 'com.example.myapplication3.MainAbility', + }; + let plainText = ''; + const pasteData = pasteboard.createData('x'.repeat(1024), dataHtml); + const record = pasteData.getRecordAt(0); + record.htmlText = htmlText; + record.plainText = plainText; + record.uri = uriText; + record.want = wantText; + const buffer = new ArrayBuffer(128); + const opt = { + size: { height: 5, width: 5 }, + pixelFormat: 3, + editable: true, + alphaType: 1, + scaleMode: 1, + }; + const pixelMap = await image.createPixelMap(buffer, opt); + record.pixelMap = pixelMap; + pasteData.replaceRecordAt(0, record); + await systemPasteboard.setPasteData(pasteData); + const hasData = await systemPasteboard.hasPasteData(); + expect(hasData).assertTrue(); + systemPasteboard.getPasteData().then((data) => { + expect(data.getRecordCount()).assertEqual(1); + expect(data.getRecordAt(0).mimeType).assertEqual('x'.repeat(1024)); + expect(data.getPrimaryWant().bundleName).assertEqual(wantText.bundleName); + expect(data.getPrimaryWant().abilityName).assertEqual(wantText.abilityName); + let newPixelMap = data.getPrimaryPixelMap(); + newPixelMap.getImageInfo().then((imageInfo) => { + expect(imageInfo.size.height).assertEqual(opt.size.height); + expect(imageInfo.size.width).assertEqual(opt.size.width); + }); + expect(data.getPrimaryUri()).assertEqual(uriText); + expect(data.getPrimaryText()).assertEqual(plainText); + expect(data.getPrimaryHtml()).assertEqual(htmlText); + done(); + }); + }); + + /** + * @tc.name pasteboard_exception_test5 + * @tc.desc Test CreateRecord throw error + * @tc.type Function + * @tc.require I5TYVJ + */ + it('pasteboard_exception_test5', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + await systemPasteboard.clearData(); + const uriText = 'https://www.baidu.com/'; + const pasteData = pasteboard.createUriData(uriText); + await systemPasteboard.setPasteData(pasteData); + const res = await systemPasteboard.hasPasteData(); + expect(res).assertEqual(true); + systemPasteboard.getPasteData().then((data) => { + const pasteData1 = data; + expect(pasteData1.getRecordCount()).assertEqual(1); + const uriText1 = 'https://www.baidu.com/1'; + const pasteDataRecord = pasteboard.createRecord(pasteboard.MIMETYPE_TEXT_URI, uriText1); + const replace = pasteData1.replaceRecordAt(0, pasteDataRecord); + expect(replace).assertEqual(true); + const primaryUri1 = pasteData1.getPrimaryUri(); + expect(primaryUri1).assertEqual(uriText1); + expect(pasteData1.hasMimeType(pasteboard.MIMETYPE_TEXT_URI)).assertEqual(true); + const primaryUri2 = pasteData1.getPrimaryUri(); + expect(primaryUri2).assertEqual(uriText1); + done(); + }); + }); + + /** + * @tc.name pasteboard_exception_test6 + * @tc.desc Test CreateRecord throw error + * @tc.type Function + * @tc.require I5TYVJ + */ + it('pasteboard_exception_test6', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + await systemPasteboard.clearData(); + const uriText6 = 'https://www.baidu.com/'; + const textData6 = 'Hello World!'; + const htmlText6 = 'Hello World!'; + const wantText6 = { + bundleName: 'com.example.myapplication3', + abilityName: 'com.example.myapplication3.MainAbility', + }; + const dataHtml6 = new ArrayBuffer(256); + const buffer6 = new ArrayBuffer(128); + const opt6 = { + size: { height: 5, width: 5 }, + pixelFormat: 3, + editable: true, + alphaType: 1, + scaleMode: 1, + }; + const pixelMap = await image.createPixelMap(buffer6, opt6); + const pasteData = pasteboard.createUriData(uriText6); + + try { + let pasteDataRecord = pasteboard.createRecord(pasteboard.MIMETYPE_TEXT_URI, uriText6); + pasteData.addRecord(pasteDataRecord); + pasteDataRecord = pasteboard.createRecord(pasteboard.MIMETYPE_TEXT_PLAIN, textData6); + pasteData.addRecord(pasteDataRecord); + pasteDataRecord = pasteboard.createRecord(pasteboard.MIMETYPE_TEXT_HTML, htmlText6); + pasteData.addRecord(pasteDataRecord); + pasteDataRecord = pasteboard.createRecord(pasteboard.MIMETYPE_TEXT_WANT, wantText6); + pasteData.addRecord(pasteDataRecord); + pasteDataRecord = pasteboard.createRecord('x'.repeat(1022), dataHtml6); + pasteData.addRecord(pasteDataRecord); + pasteDataRecord = pasteboard.createRecord(pasteboard.MIMETYPE_PIXELMAP, pixelMap); + pasteData.addRecord(pasteDataRecord); + } catch (error) { + expect(error.code === undefined).assertTrue(); + expect(error.message === undefined).assertTrue(); + expect(True === false).assertTrue(); + } + await systemPasteboard.setPasteData(pasteData); + const res = await systemPasteboard.hasPasteData(); + expect(res).assertEqual(true); + systemPasteboard.getPasteData().then((data) => { + expect(data.getRecordCount()).assertEqual(7); + let dataRecord = data.getRecordAt(3); + expect(dataRecord.htmlText).assertEqual(htmlText6); + done(); + }); + }); + + /** + * @tc.name pasteboard_exception_test7 + * @tc.desc Test CreateRecord throw error + * @tc.type Function + * @tc.require I5TYVJ + */ + it('pasteboard_exception_test7', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + await systemPasteboard.clearData(); + const uriText = 'https://www.baidu.com/'; + const htmlText = 'Hello World!'; + const pasteData = pasteboard.createUriData(uriText); + + try { + const pasteDataRecord = pasteboard.createRecord('xxddxx', htmlText); + pasteData.addRecord(pasteDataRecord); + expect(true === false).assertTrue(); + } catch (error) { + expect(error.code).assertEqual('401'); + expect(error.message).assertEqual('Parameter error. The value does not match mimeType correctly.'); + } + done(); + }); + + /** + * @tc.name pasteboard_exception_test8 + * @tc.desc Test Create Uri Data + * @tc.type Function + * @tc.require I5TYVJ + */ + it('pasteboard_exception_test8', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + await systemPasteboard.clearData(); + let uriText = 'https://www.baidu.com/'; + let pasteData = undefined; + try { + pasteData = pasteboard.createData(pasteboard.MIMETYPE_TEXT_URI, uriText); + } catch (e) { + expect(true === false).assertTrue(); + } + await systemPasteboard.setPasteData(pasteData); + const res = await systemPasteboard.hasPasteData(); + expect(res).assertEqual(true); + systemPasteboard.getPasteData().then((data) => { + expect(data.getRecordCount()).assertEqual(1); + const dataRecord = data.getRecordAt(0); + expect(dataRecord.uri).assertEqual(uriText); + done(); + }); + }); + + /** + * @tc.name pasteboard_exception_test9 + * @tc.desc Test Create htmlText Data + * @tc.type Function + * @tc.require I5TYVJ + */ + it('pasteboard_exception_test9', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + await systemPasteboard.clearData(); + const htmlText = 'Hello World!'; + let pasteData = undefined; + try { + pasteData = pasteboard.createData(pasteboard.MIMETYPE_TEXT_HTML, htmlText); + } catch (e) { + expect(true === false).assertTrue(); + } + await systemPasteboard.setPasteData(pasteData); + const res = await systemPasteboard.hasPasteData(); + expect(res).assertEqual(true); + systemPasteboard.getPasteData().then((data) => { + expect(data.getRecordCount()).assertEqual(1); + const dataRecord = data.getRecordAt(0); + expect(dataRecord.htmlText).assertEqual(htmlText); + done(); + }); + }); + + /** + * @tc.name pasteboard_exception_test10 + * @tc.desc Test Create wantText Data + * @tc.type Function + * @tc.require I5TYVJ + */ + it('pasteboard_exception_test10', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + await systemPasteboard.clearData(); + const wantText = { + bundleName: 'com.example.myapplication3', + abilityName: 'com.example.myapplication3.MainAbility', + }; + let pasteData = undefined; + try { + pasteData = pasteboard.createData(pasteboard.MIMETYPE_TEXT_WANT, wantText); + } catch (e) { + expect(true === false).assertTrue(); + } + await systemPasteboard.setPasteData(pasteData); + const res = await systemPasteboard.hasPasteData(); + expect(res).assertEqual(true); + systemPasteboard.getPasteData().then((data) => { + expect(data.getRecordCount()).assertEqual(1); + let primaryWant = data.getPrimaryWant(); + expect(primaryWant.bundleName).assertEqual(wantText.bundleName); + expect(primaryWant.abilityName).assertEqual(wantText.abilityName); + done(); + }); + }); + + /** + * @tc.name pasteboard_exception_test11 + * @tc.desc Test Create pixelMap Data + * @tc.type Function + * @tc.require I5TYVJ + */ + it('pasteboard_exception_test11', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + await systemPasteboard.clearData(); + const buffer = new ArrayBuffer(128); + const opt = { + size: { height: 5, width: 5 }, + pixelFormat: 3, + editable: true, + alphaType: 1, + scaleMode: 1, + }; + let pasteData = undefined; + const pixelMap = await image.createPixelMap(buffer, opt); + try { + pasteData = pasteboard.createData(pasteboard.MIMETYPE_PIXELMAP, pixelMap); + } catch (e) { + expect(true === false).assertTrue(); + } + await systemPasteboard.setPasteData(pasteData); + const res = await systemPasteboard.hasPasteData(); + expect(res).assertEqual(true); + systemPasteboard.getPasteData().then(async (data) => { + expect(data.getRecordCount()).assertEqual(1); + const primaryPixelMap = data.getPrimaryPixelMap(); + const PixelMapBytesNumber = primaryPixelMap.getPixelBytesNumber(); + expect(PixelMapBytesNumber).assertEqual(100); + const imageInfo = await primaryPixelMap.getImageInfo(); + expect(imageInfo.size.height === 5 && imageInfo.size.width === 5).assertEqual(true); + done(); + }); + }); + + /** + * @tc.name pasteboard_exception_test12 + * @tc.desc Test CreateData throw error + * @tc.type Function + * @tc.require I5TYVJ + */ + it('pasteboard_exception_test12', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + await systemPasteboard.clearData(); + let dataHtml = new ArrayBuffer(256); + let pasteData = undefined; + try { + pasteData = pasteboard.createData(pasteboard.MIMETYPE_PIXELMAP, dataHtml); + expect(true === false).assertTrue(); + } catch (e) { + expect(e.code).assertEqual('401'); + expect(e.message).assertEqual('Parameter error. The value does not match mimeType correctly.'); + } + done(); + }); + + /** + * @tc.name pasteboard_exception_test13 + * @tc.desc Test Create KV Data + * @tc.type Function + * @tc.require I5TYVJ + */ + it('pasteboard_exception_test13', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + await systemPasteboard.clearData(); + let dataHtml = new ArrayBuffer(256); + let pasteData = undefined; + try { + pasteData = pasteboard.createData('x'.repeat(1034), dataHtml); + expect(true === false).assertTrue(); + } catch (e) { + expect(e.code === '401').assertTrue(); + expect(e.message === 'Parameter error. The length of mimeType cannot be greater than 1024 bytes.').assertTrue(); + } + done(); + }); + + /** + * @tc.name pasteboard_exception_test14 + * @tc.desc Test addRecord throw error + * @tc.type Function + * @tc.require I5TYVJ + */ + it('pasteboard_exception_test14', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + await systemPasteboard.clearData(); + const uriText14 = 'https://www.baidu.com/'; + const textData14 = 'Hello World!'; + const htmlText14 = 'Hello World!'; + const wantText14 = { + bundleName: 'com.example.myapplication3', + abilityName: 'com.example.myapplication3.MainAbility', + }; + const dataHtml14 = new ArrayBuffer(256); + const buffer14 = new ArrayBuffer(128); + const opt14 = { + size: { height: 5, width: 5 }, + pixelFormat: 3, + editable: true, + alphaType: 1, + scaleMode: 1, + }; + const pixelMap = await image.createPixelMap(buffer14, opt14); + const pasteData = pasteboard.createData(pasteboard.MIMETYPE_TEXT_URI, uriText14); + + try { + pasteData.addRecord(pasteboard.MIMETYPE_TEXT_HTML, htmlText14); + pasteData.addRecord(pasteboard.MIMETYPE_TEXT_URI, uriText14); + pasteData.addRecord(pasteboard.MIMETYPE_TEXT_PLAIN, textData14); + pasteData.addRecord(pasteboard.MIMETYPE_PIXELMAP, pixelMap); + pasteData.addRecord(pasteboard.MIMETYPE_TEXT_WANT, wantText14); + pasteData.addRecord('x'.repeat(100), dataHtml14); + } catch (error) { + expect(true === false).assertTrue(); + } + await systemPasteboard.setPasteData(pasteData); + const res = await systemPasteboard.hasPasteData(); + expect(res).assertEqual(true); + systemPasteboard.getPasteData().then((data) => { + expect(data.getRecordCount()).assertEqual(7); + let dataRecord = data.getRecordAt(6); + expect(dataRecord.uri).assertEqual(uriText14); + let primaryPixelMap = data.getPrimaryPixelMap(); + let PixelMapBytesNumber = primaryPixelMap.getPixelBytesNumber(); + expect(PixelMapBytesNumber).assertEqual(100); + done(); + }); + }); + + /** + * @tc.name pasteboard_exception_test15 + * @tc.desc Test addRecord throw error + * @tc.type Function + * @tc.require I5TYVJ + */ + it('pasteboard_exception_test15', 0, async function (done) { + let uriText = 'https://www.baidu.com/'; + let pasteData = pasteboard.createData(pasteboard.MIMETYPE_TEXT_URI, uriText); + try { + pasteData.addRecord('xxxx', uriText); + expect(true === false).assertTrue(); + } catch (e) { + expect(e.code === '401').assertTrue(); + } + done(); + }); + + /** + * @tc.name pasteboard_exception_test16 + * @tc.desc Test addRecord throw error + * @tc.type Function + * @tc.require I5TYVJ + */ + it('pasteboard_exception_test16', 0, async function (done) { + const uriText = 'https://www.baidu.com/'; + const pasteData = pasteboard.createData(pasteboard.MIMETYPE_TEXT_URI, uriText); + const num = 600; + try { + for (let i = 0; i < num-1; i++) { + pasteData.addRecord(pasteboard.MIMETYPE_TEXT_URI, uriText); + } + expect(pasteData.getRecordCount()).assertEqual(num); + } catch (e) { + expect(e.code === '12900002').assertTrue(); + } + done(); + }); + + /** + * @tc.name pasteboard_exception_test17 + * @tc.desc Test getRecord throw error + * @tc.type Function + * @tc.require I5TYVJ + */ + it('pasteboard_exception_test17', 0, async function (done) { + const uriText = 'https://www.baidu.com/'; + const pasteData = pasteboard.createData(pasteboard.MIMETYPE_TEXT_URI, uriText); + try { + let dataRecord = pasteData.getRecord(0); + expect(dataRecord.uri).assertEqual(uriText); + } catch (e) { + expect(true === false).assertTrue(); + } + done(); + }); + + /** + * @tc.name pasteboard_exception_test18 + * @tc.desc Test getRecord throw error + * @tc.type Function + * @tc.require I5TYVJ + */ + it('pasteboard_exception_test18', 0, async function (done) { + const uriText = 'https://www.baidu.com/'; + const pasteData = pasteboard.createData(pasteboard.MIMETYPE_TEXT_URI, uriText); + try { + let dataRecord = pasteData.getRecord(5); + expect(true === false).assertTrue(); + } catch (e) { + expect(e.code === '12900001').assertTrue(); + } + done(); + }); + + /** + * @tc.name pasteboard_exception_test19 + * @tc.desc Test replaceRecord throw error + * @tc.type Function + * @tc.require I5TYVJ + */ + it('pasteboard_exception_test19', 0, async function (done) { + const uriText = 'https://www.baidu.com/'; + const uriText1 = 'https://www.baidu1.com/'; + const pasteData = pasteboard.createData(pasteboard.MIMETYPE_TEXT_URI, uriText); + const dataRecord = pasteboard.createRecord(pasteboard.MIMETYPE_TEXT_URI, uriText1); + try { + pasteData.replaceRecord(0, dataRecord); + const record = pasteData.getRecord(0); + expect(record.uri).assertEqual(uriText1); + } catch (e) { + expect(true === false).assertTrue(); + } + done(); + }); + + /** + * @tc.name pasteboard_exception_test20 + * @tc.desc Test replaceRecord throw error + * @tc.type Function + * @tc.require I5TYVJ + */ + it('pasteboard_exception_test20', 0, async function (done) { + const uriText = 'https://www.baidu.com/'; + const pasteData = pasteboard.createData(pasteboard.MIMETYPE_TEXT_URI, uriText); + try { + pasteData.replaceRecord(0, 'xxxxxx'); + expect(true === false).assertTrue(); + } catch (e) { + expect(e.code === '401').assertTrue(); + } + done(); + }); + + /** + * @tc.name pasteboard_exception_test21 + * @tc.desc Test setData + * @tc.type Function + * @tc.require I5TYVJ + */ + it('pasteboard_exception_test21', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + await systemPasteboard.clearData(); + const uriText = 'Hello//'; + const pasteData = pasteboard.createData(pasteboard.MIMETYPE_TEXT_URI, uriText); + await systemPasteboard.setData(pasteData); + const data = await systemPasteboard.hasData(); + expect(data).assertEqual(true); + systemPasteboard.getData().then((pasteData1) => { + expect(pasteData1.getRecordCount()).assertEqual(1); + expect(pasteData1.hasType(pasteboard.MIMETYPE_TEXT_URI)).assertEqual(true); + expect(pasteData1.getPrimaryUri()).assertEqual(uriText); + done(); + }); + }); + + /** + * @tc.name pasteboard_exception_test22 + * @tc.desc Test setData throw error + * @tc.type Function + * @tc.require I5TYVJ + */ + it('pasteboard_exception_test22', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + try { + systemPasteboard.setData('xxxxx'); + expect(true === false).assertTrue(); + } catch (e) { + expect(e.code === '401').assertTrue(); + expect(e.message === 'Parameter error. The Type of data must be pasteData.').assertTrue(); + } + done(); + }); + + /** + * @tc.name pasteboard_exception_test23 + * @tc.desc Test setproperty throw error + * @tc.type Function + * @tc.require I5TYVJ + */ + it('pasteboard_exception_test23', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + await systemPasteboard.clearData(); + const textData = 'Hello World!'; + const pasteData = pasteboard.createData(pasteboard.MIMETYPE_TEXT_PLAIN, textData); + const pasteDataProperty = pasteData.getProperty(); + expect(pasteDataProperty.shareOption).assertEqual(pasteboard.ShareOption.CrossDevice); + pasteDataProperty.shareOption = pasteboard.ShareOption.InApp; + pasteData.setProperty(pasteDataProperty); + expect(pasteData.getProperty().shareOption).assertEqual(pasteboard.ShareOption.InApp); + done(); + }); + + /** + * @tc.name pasteboard_exception_test24 + * @tc.desc Test setproperty throw error + * @tc.type Function + * @tc.require I5TYVJ + */ + it('pasteboard_exception_test24', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + await systemPasteboard.clearData(); + const textData = 'Hello World!'; + const pasteData = pasteboard.createData(pasteboard.MIMETYPE_TEXT_PLAIN, textData); + try { + const obj = { shareOption: 1 }; + pasteData.setProperty(obj); + expect(true === false).assertTrue(); + } catch (e) { + expect(e.code === '401').assertTrue(); + expect(e.message === 'Parameter error. The type of property must be PasteDataProperty.').assertTrue(); + } + done(); + }); + + /** + * @tc.name pasteboard_exception_test25 + * @tc.desc Test createData throw error + * @tc.type Function + * @tc.require I5TYVJ + */ + it('pasteboard_exception_test25', 0, async function (done) { + const textData = 'Hello World!'; + const dataXml = new ArrayBuffer(512); + try { + const pasteData = pasteboard.createData(pasteboard.MIMETYPE_TEXT_PLAIN, dataXml); + expect(true === false).assertTrue(); + } catch (e) { + expect(e.code === '401').assertTrue(); + expect(e.message === 'Parameter error. The value does not match mimeType correctly.').assertTrue(); + } + done(); + }); + + /** + * @tc.name pasteboard_exception_test26 + * @tc.desc Test createData throw error + * @tc.type Function + * @tc.require I5TYVJ + */ + it('pasteboard_exception_test26', 0, async function (done) { + const textData = 'Hello World!'; + const dataXml = new ArrayBuffer(512); + try { + const pasteData = pasteboard.createData('xxxxx', textData); + expect(true === false).assertTrue(); + } catch (e) { + expect(e.code === '401').assertTrue(); + expect(e.message === 'Parameter error. The value does not match mimeType correctly.').assertTrue(); + } + done(); + }); + + /** + * @tc.name pasteboard_exception_test27 + * @tc.desc Test createData throw error + * @tc.type Function + * @tc.require I5TYVJ + */ + it('pasteboard_exception_test27', 0, async function (done) { + try { + const pasteData = pasteboard.createData(pasteboard.MIMETYPE_PIXELMAP, {}); + expect(true === false).assertTrue(); + } catch (e) { + expect(e.code === '401').assertTrue(); + expect(e.message === 'Parameter error. The value does not match mimeType correctly.').assertTrue(); + } + done(); + }); +}); diff --git a/pasteboard/interfaces/kits/napi/test/unittest/pasteboardapi/PasteBoardCallbackJsunit.test .js b/pasteboard/interfaces/kits/napi/test/unittest/pasteboardapi/PasteBoardCallbackJsunit.test .js new file mode 100644 index 00000000..6e724de1 --- /dev/null +++ b/pasteboard/interfaces/kits/napi/test/unittest/pasteboardapi/PasteBoardCallbackJsunit.test .js @@ -0,0 +1,1129 @@ +/* + * Copyright (C) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the 'License'); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an 'AS IS' BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// @ts-nocheck +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from 'deccjsunit/index'; +import pasteboard from '@ohos.pasteboard'; +import image from '@ohos.multimedia.image'; + +describe('PasteBoardJSTest', function () { + beforeAll(async function () { + console.info('beforeAll'); + }); + + afterAll(async function () { + console.info('afterAll'); + }); + + /** + * @tc.name pasteboard_callback_test1 + * @tc.desc createPlainTextData test + * @tc.type Function + * @tc.require AR000HEECD + */ + it('pasteboard_callback_test1', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + systemPasteboard.clear((err, data) => { + if (err) { + console.error('f_test1: systemPasteboard.clear callback error:' + err); + return; + } + const textData1 = 'Hello World!'; + const pasteData = pasteboard.createPlainTextData(textData1); + systemPasteboard.setPasteData(pasteData, (err, data) => { + if (err) { + console.error('f_test1: systemPasteboard.setPasteData callback error:' + err); + return; + } + systemPasteboard.hasPasteData((err, data) => { + if (err) { + console.error('f_test1: systemPasteboard.hasPasteData callback error:' + err); + return; + } + expect(data).assertEqual(true); + systemPasteboard.getPasteData((err, data) => { + if (err) { + console.error('f_test1: systemPasteboard.getPasteData callback error:' + err); + return; + } + expect(data.getRecordCount()).assertEqual(1); + const primaryText1 = data.getPrimaryText(); + expect(primaryText1).assertEqual(textData1); + expect(pasteboard.MAX_RECORD_NUM).assertEqual(512); + expect(data.hasMimeType(pasteboard.MIMETYPE_TEXT_PLAIN)).assertEqual(true); + expect(data.getPrimaryMimeType()).assertEqual(pasteboard.MIMETYPE_TEXT_PLAIN); + done(); + }); + }); + }); + }); + }); + + /** + * @tc.name pasteboard_callback_test2 + * @tc.desc createHtmlData test + * @tc.type Function + * @tc.require AR000HEECD + */ + it('pasteboard_callback_test2', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + systemPasteboard.clear((err, data) => { + if (err) { + console.error('f_test2: systemPasteboard.clear callback error:' + err); + return; + } + const htmlText2 = 'Hello World!'; + const pasteData = pasteboard.createHtmlData(htmlText2); + systemPasteboard.setPasteData(pasteData, (err, data) => { + if (err) { + console.error('f_test2: systemPasteboard.setPasteData callback error:' + err); + return; + } + systemPasteboard.hasPasteData((err, data) => { + if (err) { + console.error('f_test2: systemPasteboard.hasPasteData callback error:' + err); + return; + } + expect(data).assertEqual(true); + systemPasteboard.getPasteData((err, data) => { + if (err) { + console.error('f_test2: systemPasteboard.getPasteData callback error:' + err); + return; + } + expect(data.getRecordCount()).assertEqual(1); + const PrimaryHtml2 = data.getPrimaryHtml(); + console.info('f_test2: PrimaryHtml = ' + PrimaryHtml2); + expect(PrimaryHtml2).assertEqual(htmlText2); + expect(data.hasMimeType(pasteboard.MIMETYPE_TEXT_HTML)).assertEqual(true); + expect(data.getPrimaryMimeType()).assertEqual(pasteboard.MIMETYPE_TEXT_HTML); + done(); + }); + }); + }); + }); + }); + + /** + * @tc.name pasteboard_callback_test3 + * @tc.desc 测试异步callback调用+createHtmlData,htmlText = ''. + * @tc.type Function + * @tc.require AR000HEECD + */ + it('pasteboard_callback_test3', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + systemPasteboard.clear((err, data) => { + if (err) { + console.error('f_test3: systemPasteboard.clear callback error:' + err); + return; + } + const htmlText3 = ''; + const pasteData = pasteboard.createHtmlData(htmlText3); + systemPasteboard.setPasteData(pasteData, (err, data) => { + if (err) { + console.error('f_test3: systemPasteboard.setPasteData callback error:' + err); + return; + } + systemPasteboard.hasPasteData((err, data) => { + if (err) { + console.error('f_test3: systemPasteboard.hasPasteData callback error:' + err); + return; + } + expect(data).assertEqual(true); + systemPasteboard.getPasteData((err, data) => { + if (err) { + console.error('f_test3: systemPasteboard.getPasteData callback error:' + err); + return; + } + expect(data.getRecordCount()).assertEqual(1); + const PrimaryHtml3 = data.getPrimaryHtml(); + console.info('f_test3: PrimaryHtml = ' + PrimaryHtml3); + expect(PrimaryHtml3).assertEqual(htmlText3); + expect(data.hasMimeType(pasteboard.MIMETYPE_TEXT_HTML)).assertEqual(true); + expect(data.getPrimaryMimeType()).assertEqual(pasteboard.MIMETYPE_TEXT_HTML); + done(); + }); + }); + }); + }); + }); + + /** + * @tc.name pasteboard_callback_test4 + * @tc.desc createUriData test + * @tc.type Function + * @tc.require AR000HEECD + */ + it('pasteboard_callback_test4', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + systemPasteboard.clear((err, data) => { + if (err) { + console.error('f_test4: systemPasteboard.clear callback error:' + err); + return; + } + const uriText4 = ''; + const pasteData = pasteboard.createUriData(uriText4); + systemPasteboard.setPasteData(pasteData, (err, data) => { + if (err) { + console.error('f_test4: systemPasteboard.setPasteData callback error:' + err); + return; + } + systemPasteboard.hasPasteData((err, data) => { + if (err) { + console.error('f_test4: systemPasteboard.hasPasteData callback error:' + err); + return; + } + expect(data).assertEqual(true); + systemPasteboard.getPasteData((err, data) => { + if (err) { + console.error('f_test4: systemPasteboard.getPasteData callback error:' + err); + return; + } + expect(data.getRecordCount()).assertEqual(1); + const PrimaryUri4 = data.getPrimaryUri(); + console.info('f_test4: PrimaryUri = ' + PrimaryUri4); + expect(PrimaryUri4).assertEqual(uriText4); + expect(data.hasMimeType(pasteboard.MIMETYPE_TEXT_URI)).assertEqual(true); + expect(data.getPrimaryMimeType()).assertEqual(pasteboard.MIMETYPE_TEXT_URI); + done(); + }); + }); + }); + }); + }); + + /** + * @tc.name pasteboard_callback_test5 + * @tc.desc createWantData test + * @tc.type Function + * @tc.require AR000HEECD + */ + it('pasteboard_callback_test5', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + systemPasteboard.clear((err, data) => { + if (err) { + console.error('f_test5: systemPasteboard.clear callback error:' + err); + return; + } + const want5 = { + bundleName: 'com.example.myapplication8', + abilityName: 'com.example.myapplication8.MainAbility', + }; + const pasteData = pasteboard.createWantData(want5); + systemPasteboard.setPasteData(pasteData, (err, data) => { + if (err) { + console.error('f_test5: systemPasteboard.setPasteData callback error:' + err); + return; + } + systemPasteboard.hasPasteData((err, data) => { + if (err) { + console.error('f_test5: systemPasteboard.hasPasteData callback error:' + err); + return; + } + expect(data).assertEqual(true); + systemPasteboard.getPasteData((err, data) => { + if (err) { + console.error('f_test5: systemPasteboard.getPasteData callback error:' + err); + return; + } + expect(data.getRecordCount()).assertEqual(1); + const PrimaryWant5 = data.getPrimaryWant(); + expect(PrimaryWant5.bundleName).assertEqual(want5.bundleName); + expect(PrimaryWant5.abilityName).assertEqual(want5.abilityName); + expect(data.hasMimeType(pasteboard.MIMETYPE_TEXT_WANT)).assertEqual(true); + expect(data.getPrimaryMimeType()).assertEqual(pasteboard.MIMETYPE_TEXT_WANT); + done(); + }); + }); + }); + }); + }); + + /** + * @tc.name pasteboard_callback_test6 + * @tc.desc addTextRecord test + * @tc.type Function + * @tc.require AR000HEECD + */ + it('pasteboard_callback_test6', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + systemPasteboard.clear((err, data) => { + if (err) { + console.error('f_test6: systemPasteboard.clear callback error:' + err); + return; + } + const textData6 = 'Hello World!'; + const pasteData = pasteboard.createPlainTextData(textData6); + const textData62 = 'Hello World1'; + pasteData.addTextRecord(textData62); + systemPasteboard.setPasteData(pasteData, (err, data) => { + if (err) { + console.error('f_test6: systemPasteboard.setPasteData callback error:' + err); + return; + } + systemPasteboard.hasPasteData((err, data) => { + if (err) { + console.error('f_test6: systemPasteboard.hasPasteData callback error:' + err); + return; + } + expect(data).assertEqual(true); + systemPasteboard.getPasteData((err, data) => { + if (err) { + console.error('f_test6: systemPasteboard.getPasteData callback error:' + err); + return; + } + expect(data.getRecordCount()).assertEqual(2); + const PrimaryText6 = data.getPrimaryText(); + expect(PrimaryText6).assertEqual(textData62); + expect(data.hasMimeType(pasteboard.MIMETYPE_TEXT_PLAIN)).assertEqual(true); + expect(data.getPrimaryMimeType()).assertEqual(pasteboard.MIMETYPE_TEXT_PLAIN); + done(); + }); + }); + }); + }); + }); + + /** + * @tc.name pasteboard_callback_test7 + * @tc.desc addTextRecord test + * @tc.type Function + * @tc.require AR000HEECD + */ + it('pasteboard_callback_test7', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + systemPasteboard.clear((err, data) => { + if (err) { + console.error('f_test7: systemPasteboard.clear callback error:' + err); + return; + } + const textData71 = 'Hello World!'; + const pasteData = pasteboard.createPlainTextData(textData71); + let textData7 = ''; + for (let i = 1; i < 15; i++) { + textData7 = 'Hello World'; + textData7 = textData7 + i; + pasteData.addTextRecord(textData7); + } + systemPasteboard.setPasteData(pasteData, (err, data) => { + if (err) { + console.error('f_test7: systemPasteboard.setPasteData callback error:' + err); + return; + } + systemPasteboard.hasPasteData((err, data) => { + if (err) { + console.error('f_test7: systemPasteboard.hasPasteData callback error:' + err); + return; + } + expect(data).assertEqual(true); + systemPasteboard.getPasteData((err, data) => { + if (err) { + console.error('f_test7: systemPasteboard.getPasteData callback error:' + err); + return; + } + expect(data.getRecordCount()).assertEqual(15); + const PrimaryText7 = data.getPrimaryText(); + expect(data.hasMimeType(pasteboard.MIMETYPE_TEXT_PLAIN)).assertEqual(true); + expect(data.getPrimaryMimeType()).assertEqual(pasteboard.MIMETYPE_TEXT_PLAIN); + expect(PrimaryText7).assertEqual('Hello World14'); + done(); + }); + }); + }); + }); + }); + + /** + * @tc.name pasteboard_callback_test8 + * @tc.desc addHtmlRecord+addUriRecord+addWantRecord + * @tc.type Function + * @tc.require AR000HEECD + */ + it('pasteboard_callback_test8', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + systemPasteboard.clear((err, data) => { + if (err) { + console.error('f_test8: systemPasteboard.clear callback error:' + err); + return; + } + const textData8 = 'Hello World!'; + const pasteData = pasteboard.createPlainTextData(textData8); + const htmlText8 = 'Hello World!'; + pasteData.addHtmlRecord(htmlText8); + const uriText8 = ''; + pasteData.addUriRecord(uriText8); + const want8 = { + bundleName: 'com.example.myapplication8', + abilityName: 'com.example.myapplication8.MainAbility', + }; + pasteData.addWantRecord(want8); + systemPasteboard.setPasteData(pasteData, (err, data) => { + if (err) { + console.error('f_test8: systemPasteboard.setPasteData callback error:' + err); + return; + } + systemPasteboard.hasPasteData((err, data) => { + if (err) { + console.error('f_test8: systemPasteboard.hasPasteData callback error:' + err); + return; + } + expect(data).assertEqual(true); + systemPasteboard.getPasteData((err, data) => { + if (err) { + console.error('f_test8: systemPasteboard.getPasteData callback error:' + err); + return; + } + expect(data.getRecordCount()).assertEqual(4); + const MimeTypes8 = data.getMimeTypes(); + expect(MimeTypes8[0]).assertEqual(pasteboard.MIMETYPE_TEXT_WANT); + expect(MimeTypes8[1]).assertEqual(pasteboard.MIMETYPE_TEXT_URI); + expect(MimeTypes8[2]).assertEqual(pasteboard.MIMETYPE_TEXT_HTML); + expect(MimeTypes8[3]).assertEqual(pasteboard.MIMETYPE_TEXT_PLAIN); + done(); + }); + }); + }); + }); + }); + + /** + * @tc.name pasteboard_callback_test9 + * @tc.desc addHtmlRecord+addUriRecord+removeRecordAt + * @tc.type Function + * @tc.require AR000HEECD + */ + it('pasteboard_callback_test9', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + systemPasteboard.clear((err, data) => { + if (err) { + console.error('f_test9: systemPasteboard.clear callback error:' + err); + return; + } + const textData9 = 'Hello World!'; + const pasteData = pasteboard.createPlainTextData(textData9); + const htmlText9 = 'Hello World!'; + pasteData.addHtmlRecord(htmlText9); + const uriText9 = ''; + pasteData.addUriRecord(uriText9); + systemPasteboard.setPasteData(pasteData, (err, data) => { + if (err) { + console.error('f_test9: systemPasteboard.setPasteData callback error:' + err); + return; + } + systemPasteboard.hasPasteData((err, data) => { + if (err) { + console.error('f_test9: systemPasteboard.hasPasteData callback error:' + err); + return; + } + expect(data).assertEqual(true); + systemPasteboard.getPasteData((err, data) => { + if (err) { + console.error('f_test9: systemPasteboard.getPasteData callback error:' + err); + return; + } + expect(data.getRecordCount()).assertEqual(3); + expect(data.removeRecordAt(0)).assertEqual(true); + expect(data.getRecordCount()).assertEqual(2); + systemPasteboard.setPasteData(data, (err, newdata) => { + if (err) { + console.error('f_test9: systemPasteboard.setPasteData callback error:' + err); + return; + } + systemPasteboard.getPasteData((err, data) => { + if (err) { + console.error('f_test9: systemPasteboard.getPasteData callback error:' + err); + return; + } + expect(data.getRecordCount()).assertEqual(2); + done(); + }); + }); + }); + }); + }); + }); + }); + + /** + * @tc.name pasteboard_callback_test10 + * @tc.desc Add 30 TextRecords + * @tc.type Function + * @tc.require AR000H5GKU + */ + it('pasteboard_callback_test10', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + systemPasteboard.clear((err, data) => { + if (err) { + console.error('f_test10: systemPasteboard.clear callback error:' + err); + return; + } + const textData101 = 'Hello World!'; + const pasteData = pasteboard.createPlainTextData(textData101); + let textData10 = ''; + for (let i = 1; i < 30; i++) { + textData10 = 'Hello World'; + textData10 = textData10 + i; + pasteData.addTextRecord(textData10); + } + systemPasteboard.setPasteData(pasteData, (err, data) => { + if (err) { + console.error('f_test10: systemPasteboard.setPasteData callback error:' + err); + return; + } + systemPasteboard.hasPasteData((err, data) => { + if (err) { + console.error('f_test10: systemPasteboard.hasPasteData callback error:' + err); + return; + } + expect(data).assertEqual(true); + systemPasteboard.getPasteData((err, data) => { + if (err) { + console.error('f_test10: systemPasteboard.getPasteData callback error:' + err); + return; + } + expect(data.getRecordCount()).assertEqual(30); + for (let i = 0; i < 30; i++) { + expect(data.removeRecordAt(0)).assertEqual(true); + } + expect(data.getRecordCount()).assertEqual(0); + systemPasteboard.setPasteData(data, (err, newdata) => { + if (err) { + console.error('f_test10: systemPasteboard.setPasteData callback error:' + err); + return; + } + systemPasteboard.getPasteData((err, data) => { + if (err) { + console.error('f_test10: systemPasteboard.getPasteData callback error:' + err); + return; + } + expect(data.getRecordCount() == 0).assertEqual(true); + done(); + }); + }); + }); + }); + }); + }); + }); + + /** + * @tc.name pasteboard_callback_test11 + * @tc.desc Replcae textRecord + * @tc.type Function + * @tc.require AR000H5GKU + */ + it('pasteboard_callback_test11', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + systemPasteboard.clear((err, data) => { + if (err) { + console.error('f_test11: systemPasteboard.clear callback error:' + err); + return; + } + const textData11 = 'Hello World!'; + const pasteData = pasteboard.createPlainTextData(textData11); + systemPasteboard.setPasteData(pasteData, (err, data) => { + if (err) { + console.error('f_test11: systemPasteboard.setPasteData callback error:' + err); + return; + } + systemPasteboard.hasPasteData((err, data) => { + if (err) { + console.error('f_test11: systemPasteboard.hasPasteData callback error:' + err); + return; + } + expect(data).assertEqual(true); + systemPasteboard.getPasteData((err, data) => { + if (err) { + console.error('f_test11: systemPasteboard.getPasteData callback error:' + err); + return; + } + expect(data.getRecordCount()).assertEqual(1); + const textData111 = 'Hello World1'; + const pasteDataRecord11 = pasteboard.createPlainTextRecord(textData111); + const replace11 = data.replaceRecordAt(0, pasteDataRecord11); + expect(replace11).assertEqual(true); + const primaryText11 = data.getPrimaryText(); + expect(primaryText11).assertEqual(textData111); + done(); + }); + }); + }); + }); + }); + + /** + * @tc.name pasteboard_callback_test12 + * @tc.desc Replcae htmlRecord + * @tc.type Function + * @tc.require AR000H5GKU + */ + it('pasteboard_callback_test12', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + systemPasteboard.clear((err, data) => { + if (err) { + console.error('f_test12: systemPasteboard.clear callback error:' + err); + return; + } + const htmlText12 = 'Hello World!'; + const pasteData = pasteboard.createHtmlData(htmlText12); + systemPasteboard.setPasteData(pasteData, (err, data) => { + if (err) { + console.error('f_test12: systemPasteboard.setPasteData callback error:' + err); + return; + } + systemPasteboard.hasPasteData((err, data) => { + if (err) { + console.error('f_test12: systemPasteboard.hasPasteData callback error:' + err); + return; + } + expect(data).assertEqual(true); + systemPasteboard.getPasteData((err, data) => { + if (err) { + console.error('f_test12: systemPasteboard.getPasteData callback error:' + err); + return; + } + expect(data.getRecordCount()).assertEqual(1); + const htmlText121 = 'Hello World 1'; + const pasteDataRecord12 = pasteboard.createHtmlTextRecord(htmlText121); + const replace12 = data.replaceRecordAt(0, pasteDataRecord12); + expect(replace12).assertEqual(true); + expect(data.getRecordCount()).assertEqual(1); + const primaryHtml12 = data.getPrimaryHtml(); + expect(primaryHtml12).assertEqual(htmlText121); + done(); + }); + }); + }); + }); + }); + + /** + * @tc.name pasteboard_callback_test13 + * @tc.desc Replcae wantRecord + * @tc.type Function + * @tc.require AR000H5GKU + */ + it('pasteboard_callback_test13', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + systemPasteboard.clear((err, data) => { + if (err) { + console.error('f_test13: systemPasteboard.clear callback error:' + err); + return; + } + const wantText13 = { + bundleName: 'com.example.myapplication3', + abilityName: 'com.example.myapplication3.MainAbility', + }; + const pasteData = pasteboard.createData(pasteboard.MIMETYPE_TEXT_WANT, wantText13); + systemPasteboard.setPasteData(pasteData, (err, data) => { + if (err) { + console.error('f_test13: systemPasteboard.setPasteData callback error:' + err); + return; + } + systemPasteboard.hasPasteData((err, data) => { + if (err) { + console.error('f_test13: systemPasteboard.hasPasteData callback error:' + err); + return; + } + expect(data).assertEqual(true); + systemPasteboard.getPasteData((err, data) => { + if (err) { + console.error('f_test13: systemPasteboard.getPasteData callback error:' + err); + return; + } + expect(data.getRecordCount()).assertEqual(1); + const getWantText13 = { + bundleName: 'com.example.myapplication30', + abilityName: 'com.example.myapplication30.MainAbility', + }; + const pasteDataRecord13 = pasteboard.createRecord(pasteboard.MIMETYPE_TEXT_WANT, getWantText13); + const replace13 = data.replaceRecordAt(0, pasteDataRecord13); + expect(replace13).assertEqual(true); + const primaryWant13 = data.getPrimaryWant(); + expect(data.hasMimeType(pasteboard.MIMETYPE_TEXT_WANT)).assertEqual(true); + expect(primaryWant13.bundleName).assertEqual(getWantText13.bundleName); + expect(primaryWant13.abilityName).assertEqual(getWantText13.abilityName); + done(); + }); + }); + }); + }); + }); + + /** + * @tc.name pasteboard_callback_test14 + * @tc.desc get pasteData after clear wantData + * @tc.type Function + * @tc.require AR000H5GKU + */ + it('pasteboard_callback_test14', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + systemPasteboard.clear((err, data) => { + if (err) { + console.error('f_test14: systemPasteboard.clear callback error:' + err); + return; + } + const wantText14 = { + bundleName: 'com.example.myapplication3', + abilityName: 'com.example.myapplication3.MainAbility', + }; + const pasteData = pasteboard.createWantData(wantText14); + systemPasteboard.setPasteData(pasteData, (err, data) => { + if (err) { + console.error('f_test14: systemPasteboard.setPasteData callback error:' + err); + return; + } + systemPasteboard.hasPasteData((err, data) => { + if (err) { + console.error('f_test14: systemPasteboard.hasPasteData callback error:' + err); + return; + } + expect(data).assertEqual(true); + systemPasteboard.getPasteData((err, data) => { + if (err) { + console.error('f_test14: systemPasteboard.getPasteData callback error:' + err); + return; + } + expect(data.getRecordCount()).assertEqual(1); + systemPasteboard.clear((err, data) => { + if (err) { + console.error('f_test14: systemPasteboard.clear callback error:' + err); + return; + } + systemPasteboard.getPasteData((err, data) => { + if (err) { + console.error('f_test14: systemPasteboard.getPasteData callback error:' + err); + return; + } + expect(data.getRecordCount()).assertEqual(0); + done(); + }); + }); + }); + }); + }); + }); + }); + + /** + * @tc.name pasteboard_callback_test15 + * @tc.desc getProperty and setProperty test + * @tc.require AR000H5GKU + */ + it('pasteboard_callback_test15', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + systemPasteboard.clear((err, data) => { + if (err) { + console.error('f_test15: systemPasteboard.clear callback error:' + err); + return; + } + const textData15 = 'Hello World!'; + const pasteData = pasteboard.createPlainTextData(textData15); + systemPasteboard.setPasteData(pasteData, (err, data) => { + if (err) { + console.error('f_test15: systemPasteboard.setPasteData callback error:' + err); + return; + } + systemPasteboard.hasPasteData((err, data) => { + if (err) { + console.error('f_test15: systemPasteboard.hasPasteData callback error:' + err); + return; + } + expect(data).assertEqual(true); + systemPasteboard.getPasteData((err, data) => { + if (err) { + console.error('f_test15: systemPasteboard.getPasteData callback error:' + err); + return; + } + expect(data.getRecordCount()).assertEqual(1); + const pasteDataProperty15 = data.getProperty(); + expect(pasteDataProperty15.shareOption).assertEqual(pasteboard.ShareOption.CrossDevice); + pasteDataProperty15.shareOption = pasteboard.ShareOption.InApp; + data.setProperty(pasteDataProperty15); + const getPasteDataProperty15 = data.getProperty(); + expect(getPasteDataProperty15.shareOption).assertEqual(pasteboard.ShareOption.InApp); + done(); + }); + }); + }); + }); + }); + + /** + * @tc.name pasteboard_callback_test16 + * @tc.desc on test + * @tc.type Function + * @tc.require AR000H5GKU + */ + it('pasteboard_callback_test16', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + systemPasteboard.clear((err, data) => { + if (err) { + console.error('f_test16: systemPasteboard.clear callback error:' + err); + return; + } + systemPasteboard.on('update', contentChanges); + const textData16 = 'Hello World!'; + const pasteData = pasteboard.createPlainTextData(textData16); + systemPasteboard.setPasteData(pasteData, (err, data) => { + if (err) { + console.error('f_test16: systemPasteboard.setPasteData callback error:' + err); + return; + } + systemPasteboard.hasPasteData((err, data) => { + if (err) { + console.error('f_test16: systemPasteboard.hasPasteData callback error:' + err); + return; + } + expect(data === true).assertEqual(true); + systemPasteboard.getPasteData((err, data) => { + if (err) { + console.error('f_test16: systemPasteboard.getPasteData callback error:' + err); + return; + } + expect(data.getRecordCount() == 1).assertEqual(true); + expect(data.removeRecordAt(0)).assertEqual(true); + expect(data.getRecordCount() == 0).assertEqual(true); + done(); + }); + }); + }); + }); + }); + + /** + * @tc.name pasteboard_callback_test17 + * @tc.desc off test + * @tc.type Function + * @tc.require AR000H5GKU + */ + it('pasteboard_callback_test17', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + systemPasteboard.clear((err, data) => { + if (err) { + console.error('f_test17: systemPasteboard.clear callback error:' + err); + return; + } + systemPasteboard.off('update', contentChanges); + const textData17 = 'Hello World!'; + const pasteData = pasteboard.createPlainTextData(textData17); + systemPasteboard.setPasteData(pasteData, (err, data) => { + if (err) { + console.error('f_test17: systemPasteboard.setPasteData callback error:' + err); + return; + } + systemPasteboard.hasPasteData((err, data) => { + if (err) { + console.error('f_test17: systemPasteboard.hasPasteData callback error:' + err); + return; + } + expect(data).assertEqual(true); + systemPasteboard.getPasteData((err, data) => { + if (err) { + console.error('f_test17: systemPasteboard.getPasteData callback error:' + err); + return; + } + expect(data.getRecordCount()).assertEqual(1); + expect(data.removeRecordAt(0)).assertEqual(true); + expect(data.getRecordCount()).assertEqual(0); + done(); + }); + }); + }); + }); + }); + + /** + * @tc.name pasteboard_callback_test18 + * @tc.desc createRecord test + * @tc.type Function + * @tc.require AR000H5GKU + */ + it('pasteboard_callback_test18', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + systemPasteboard.clear().then(() => { + const buffer18 = new ArrayBuffer(128); + const opt18 = { + size: { height: 5, width: 5 }, + pixelFormat: 3, + editable: true, + alphaType: 1, + scaleMode: 1, + }; + const pasteData = pasteboard.createHtmlData('application/xml'); + image.createPixelMap(buffer18, opt18).then((pixelMap) => { + expect(pixelMap.getPixelBytesNumber()).assertEqual(100); + const pixelMapRecord18 = pasteboard.createRecord(pasteboard.MIMETYPE_PIXELMAP, pixelMap); + pasteData.addRecord(pixelMapRecord18); + systemPasteboard.setPasteData(pasteData).then(() => { + systemPasteboard.hasPasteData().then((data) => { + expect(data).assertEqual(true); + systemPasteboard.getPasteData().then((newPasteData) => { + const recordCount18 = newPasteData.getRecordCount(); + expect(recordCount18).assertEqual(2); + const newPixelMap18 = newPasteData.getPrimaryPixelMap(); + const PixelMapBytesNumber18 = newPixelMap18.getPixelBytesNumber(); + expect(PixelMapBytesNumber18).assertEqual(100); + const newHtmlData18 = newPasteData.getRecordAt(1); + expect(newHtmlData18.htmlText).assertEqual('application/xml'); + newPixelMap18.getImageInfo().then((imageInfo) => { + expect(imageInfo.size.height === 5 && imageInfo.size.width === 5).assertEqual(true); + done(); + }); + }); + }); + }); + }); + }); + }); + + /** + * @tc.name pasteboard_callback_test19 + * @tc.desc Add plainText、htmlText、uriText record + * @tc.type Function + * @tc.require AR000H5GKU + */ + it('pasteboard_callback_test19', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + systemPasteboard.clear((err, data) => { + if (err) { + console.error('f_test19: systemPasteboard.clear callback error:' + err); + return; + } + const textData191 = 'Hello World0'; + const pasteData = pasteboard.createPlainTextData(textData191); + let textData19 = ''; + for (let i = 1; i < 5; i++) { + textData19 = 'Hello World'; + textData19 = textData19 + i; + pasteData.addTextRecord(textData19); + } + let htmlText19 = ''; + for (let i = 0; i < 5; i++) { + htmlText19 = 'Hello World!'; + htmlText19 = htmlText19 + i; + pasteData.addHtmlRecord(htmlText19); + } + let uriText19 = ''; + for (let i = 0; i < 5; i++) { + uriText19 = 'https://www.baidu.com/'; + uriText19 = uriText19 + i; + pasteData.addUriRecord(uriText19); + } + systemPasteboard.setPasteData(pasteData, (err, data) => { + if (err) { + console.error('f_test19: systemPasteboard.setPasteData callback error:' + err); + return; + } + systemPasteboard.hasPasteData((err, data) => { + if (err) { + console.error('f_test19: systemPasteboard.hasPasteData callback error:' + err); + return; + } + expect(data).assertEqual(true); + systemPasteboard.getPasteData(async (err, data) => { + if (err) { + console.error('f_test19: systemPasteboard.getPasteData callback error:' + err); + return; + } + expect(data.getRecordCount()).assertEqual(15); + await systemPasteboard.clear(); + let newData19 = await systemPasteboard.getPasteData(); + expect(newData19.getRecordCount()).assertEqual(0); + done(); + }); + }); + }); + }); + }); + + /** + * @tc.name pasteboard_callback_test20 + * @tc.desc convertToText test + * @tc.type Function + * @tc.require AR000H5GKU + */ + it('pasteboard_callback_test20', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + systemPasteboard.clear((err, data) => { + if (err) { + console.error('f_test20: systemPasteboard.clear callback error:' + err); + return; + } + const textData20 = 'Hello World!'; + const pasteData = pasteboard.createPlainTextData(textData20); + systemPasteboard.setPasteData(pasteData, (err, data) => { + if (err) { + console.error('f_test20: systemPasteboard.setPasteData callback error:' + err); + return; + } + systemPasteboard.hasPasteData((err, data) => { + if (err) { + console.error('f_test20: systemPasteboard.hasPasteData callback error:' + err); + return; + } + expect(data).assertEqual(true); + systemPasteboard.getPasteData(async (err, data) => { + if (err) { + console.error('f_test20: systemPasteboard.getPasteData callback error:' + err); + return; + } + expect(data.getRecordCount()).assertEqual(1); + const dataRecord20 = data.getRecordAt(0); + const text = await dataRecord20.convertToText(); + expect(text).assertEqual(textData20); + done(); + }); + }); + }); + }); + }); + + /** + * @tc.name pasteboard_callback_test21 + * @tc.desc convertToText test + * @tc.type Function + * @tc.require AR000H5GKU + */ + it('pasteboard_callback_test21', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + systemPasteboard.clear((err, data) => { + if (err) { + console.error('f_test21: systemPasteboard.clear callback error:' + err); + return; + } + const textData21 = 'Hello World!'; + const pasteData = pasteboard.createPlainTextData(textData21); + systemPasteboard.setPasteData(pasteData, (err, data) => { + if (err) { + console.error('f_test21: systemPasteboard.setPasteData callback error:' + err); + return; + } + systemPasteboard.hasPasteData((err, data) => { + if (err) { + console.error('f_test21: systemPasteboard.hasPasteData callback error:' + err); + return; + } + expect(data).assertEqual(true); + systemPasteboard.getPasteData((err, data) => { + if (err) { + console.error('f_test21: systemPasteboard.getPasteData callback error:' + err); + return; + } + expect(data.getRecordCount()).assertEqual(1); + const dataRecord21 = data.getRecordAt(0); + dataRecord21.convertToText((err, data) => { + if (err) { + console.error('f_test21: PasteDataRecord.convertToText callback error:' + err); + return; + } + expect(data).assertEqual(textData21); + done(); + }); + }); + }); + }); + }); + }); + + /** + * @tc.name pasteboard_callback_test22 + * @tc.desc convertToText test + * @tc.type Function + * @tc.require AR000H5GKU + */ + it('pasteboard_callback_test22', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + systemPasteboard.clear((err, data) => { + if (err) { + console.error('f_test22: systemPasteboard.clear callback error:' + err); + return; + } + const textData22 = 'Hello 中国!@#$%^&*()_+{}\\?.'; + const pasteData = pasteboard.createPlainTextData(textData22); + systemPasteboard.setPasteData(pasteData, (err, data) => { + if (err) { + console.error('f_test22: systemPasteboard.setPasteData callback error:' + err); + return; + } + systemPasteboard.hasPasteData((err, data) => { + if (err) { + console.error('f_test22: systemPasteboard.hasPasteData callback error:' + err); + return; + } + expect(data).assertEqual(true); + systemPasteboard.getPasteData(async (err, data) => { + if (err) { + console.error('f_test22: systemPasteboard.getPasteData callback error:' + err); + return; + } + expect(data.getRecordCount()).assertEqual(1); + const dataRecord22 = data.getRecordAt(0); + const text = await dataRecord22.convertToText(); + expect(text).assertEqual(textData22); + done(); + }); + }); + }); + }); + }); + + /** + * @tc.name pasteboard_callback_test23 + * @tc.desc convertToText test + * @tc.type Function + * @tc.require AR000H5GKU + */ + it('pasteboard_callback_test23', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + systemPasteboard.clear((err, data) => { + if (err) { + console.error('f_test23: systemPasteboard.clear callback error:' + err); + return; + } + const uriText23 = 'https://www.baidu.com/'; + const pasteData = pasteboard.createUriData(uriText23); + systemPasteboard.setPasteData(pasteData, (err, data) => { + if (err) { + console.error('f_test23: systemPasteboard.setPasteData callback error:' + err); + return; + } + systemPasteboard.hasPasteData((err, data) => { + if (err) { + console.error('f_test23: systemPasteboard.hasPasteData callback error:' + err); + return; + } + expect(data).assertEqual(true); + systemPasteboard.getPasteData(async (err, data) => { + if (err) { + console.error('f_test23: systemPasteboard.getPasteData callback error:' + err); + return; + } + expect(data.getRecordCount()).assertEqual(1); + const dataRecord23 = data.getRecordAt(0); + const text = await dataRecord23.convertToText(); + expect(text).assertEqual(uriText23); + done(); + }); + }); + }); + }); + }); + + /** + * The callback function is used for pasteboard content changes + */ + function contentChanges() { + console.info('#EVENT: The content is changed in the pasteboard'); + } +}); diff --git a/pasteboard/interfaces/kits/napi/test/unittest/pasteboardapi/PasteBoardPromiseJsunit.test.js b/pasteboard/interfaces/kits/napi/test/unittest/pasteboardapi/PasteBoardPromiseJsunit.test.js new file mode 100644 index 00000000..ab02b049 --- /dev/null +++ b/pasteboard/interfaces/kits/napi/test/unittest/pasteboardapi/PasteBoardPromiseJsunit.test.js @@ -0,0 +1,1494 @@ +/* + * Copyright (C) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the 'License'); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an 'AS IS' BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// @ts-nocheck +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from 'deccjsunit/index'; +import pasteboard from '@ohos.pasteboard'; +import image from '@ohos.multimedia.image'; + +describe('PasteBoardJSTest', function () { + beforeAll(async function () { + console.info('beforeAll'); + }); + + afterAll(async function () { + console.info('afterAll'); + }); + + /** + * @tc.name pasteboard_promise_test1 + * @tc.desc Adds PlainTextData + * @tc.type Function + * @tc.require AR000H5HVI + */ + it('pasteboard_promise_test1', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + await systemPasteboard.clearData(); + const textData1 = 'Hello World!'; + const pasteData = pasteboard.createPlainTextData(textData1); + await systemPasteboard.setPasteData(pasteData); + const res = await systemPasteboard.hasPasteData(); + expect(res).assertEqual(true); + const types = pasteData.getMimeTypes(); + expect('text/plain').assertEqual(types[0]); + systemPasteboard.getPasteData().then((data) => { + const pasteData1 = data; + expect(pasteData1.getRecordCount()).assertEqual(1); + const primaryText = pasteData1.getPrimaryText(); + expect(primaryText).assertEqual(textData1); + expect(pasteboard.MAX_RECORD_NUM).assertEqual(512); + expect(pasteData1.getPrimaryMimeType()).assertEqual(pasteboard.MIMETYPE_TEXT_PLAIN); + done(); + }); + }); + + /** + * @tc.name pasteboard_promise_test2 + * @tc.desc Adds PlainTextData = '' + * @tc.type Function + * @tc.require AR000H5HVI + */ + it('pasteboard_promise_test2', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + await systemPasteboard.clearData(); + const textData2 = ''; + const pasteData = pasteboard.createPlainTextData(textData2); + await systemPasteboard.setPasteData(pasteData); + const res2 = await systemPasteboard.hasPasteData(); + expect(res2).assertEqual(true); + systemPasteboard.getPasteData().then((data) => { + const recordCount2 = data.getRecordCount(); + expect(recordCount2).assertEqual(1); + done(); + }); + }); + + /** + * @tc.name pasteboard_promise_test3 + * @tc.desc Adds PlainTextData = 'Hello 中国!@#$%^&*()_+{}\?.' + * @tc.type Function + * @tc.require AR000H5HVI + */ + it('pasteboard_promise_test3', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + await systemPasteboard.clearData(); + const textData3 = 'Hello 中国!@#$%^&*()_+{}?.'; + const pasteData = pasteboard.createPlainTextData(textData3); + await systemPasteboard.setPasteData(pasteData); + const res3 = await systemPasteboard.hasPasteData(); + expect(res3).assertEqual(true); + systemPasteboard.getPasteData().then((data) => { + const pasteData3 = data; + expect(pasteData3.getRecordCount()).assertEqual(1); + const primaryText = pasteData3.getPrimaryText(); + expect(primaryText).assertEqual(textData3); + expect(pasteData3.hasMimeType(pasteboard.MIMETYPE_TEXT_PLAIN)).assertEqual(true); + done(); + }); + }); + + /** + * @tc.name pasteboard_promise_test4 + * @tc.desc Adds 300K PlainTextData + * @tc.type Function + * @tc.require AR000H5HVI + */ + it('pasteboard_promise_test4', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + await systemPasteboard.clearData(); + let textData4 = ''; + for (let i = 0; i < 300; i++) { + textData4 = textData4 + 'A'; + } + const pasteData = pasteboard.createPlainTextData(textData4); + await systemPasteboard.setPasteData(pasteData); + const res4 = await systemPasteboard.hasPasteData(); + expect(res4).assertEqual(true); + systemPasteboard.getPasteData().then((data) => { + const pasteData4 = data; + expect(pasteData4.getRecordCount()).assertEqual(1); + const primaryText = pasteData4.getPrimaryText(); + expect(primaryText).assertEqual(textData4); + expect(pasteData4.hasMimeType(pasteboard.MIMETYPE_TEXT_PLAIN)).assertEqual(true); + expect(pasteData4.getPrimaryMimeType()).assertEqual(pasteboard.MIMETYPE_TEXT_PLAIN); + done(); + }); + }); + + /** + * @tc.name pasteboard_promise_test5 + * @tc.desc Adds htmlText + * @tc.type Function + * @tc.require AR000H5HVI + */ + it('pasteboard_promise_test5', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + await systemPasteboard.clearData(); + const htmlText5 = 'Hello World!'; + const pasteData = pasteboard.createHtmlData(htmlText5); + await systemPasteboard.setPasteData(pasteData); + const res5 = await systemPasteboard.hasPasteData(); + expect(res5).assertEqual(true); + systemPasteboard.getPasteData().then((data) => { + const pasteData5 = data; + expect(pasteData5.getRecordCount()).assertEqual(1); + const primaryHtml6 = pasteData5.getPrimaryHtml(); + expect(primaryHtml6).assertEqual(htmlText5); + expect(pasteData5.hasMimeType(pasteboard.MIMETYPE_TEXT_HTML)).assertEqual(true); + expect(pasteData5.getPrimaryMimeType()).assertEqual(pasteboard.MIMETYPE_TEXT_HTML); + done(); + }); + }); + + /** + * @tc.name pasteboard_promise_test6 + * @tc.desc Adds htmlText = '' + * @tc.type Function + * @tc.require AR000H5HVI + */ + it('pasteboard_promise_test6', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + await systemPasteboard.clearData(); + const htmlText6 = ''; + const pasteData = pasteboard.createHtmlData(htmlText6); + await systemPasteboard.setPasteData(pasteData); + const res6 = await systemPasteboard.hasPasteData(); + expect(res6).assertEqual(true); + systemPasteboard.getPasteData().then((data) => { + expect(data.getRecordCount()).assertEqual(1); + const primaryHtml6 = data.getPrimaryHtml(); + expect(primaryHtml6).assertEqual(htmlText6); + expect(data.hasMimeType(pasteboard.MIMETYPE_TEXT_HTML)).assertEqual(true); + expect(data.getPrimaryMimeType()).assertEqual(pasteboard.MIMETYPE_TEXT_HTML); + done(); + }); + }); + + /** + * @tc.name pasteboard_promise_test7 + * @tc.desc Adds htmlText = 'Hello 中国!@#$%^&*()_+{}\?.' + * @tc.type Function + * @tc.require AR000H5HVI + */ + it('pasteboard_promise_test7', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + await systemPasteboard.clearData(); + const htmlText = 'Hello 中国!@#$%^&*()_+{}?.'; + const pasteData = pasteboard.createHtmlData(htmlText); + await systemPasteboard.setPasteData(pasteData); + const res = await systemPasteboard.hasPasteData(); + expect(res).assertEqual(true); + systemPasteboard.getPasteData().then((data) => { + expect(data.getRecordCount()).assertEqual(1); + expect(data.hasMimeType(pasteboard.MIMETYPE_TEXT_HTML)).assertEqual(true); + expect(data.getPrimaryMimeType()).assertEqual(pasteboard.MIMETYPE_TEXT_HTML); + expect(data.getPrimaryHtml()).assertEqual(htmlText); + done(); + }); + }); + + /** + * @tc.name pasteboard_promise_test8 + * @tc.desc Adds uriText + * @tc.type Function + * @tc.require AR000H5HVI + */ + it('pasteboard_promise_test8', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + await systemPasteboard.clearData(); + const uriText8 = 'https://www.baidu.com/'; + const pasteData = pasteboard.createUriData(uriText8); + await systemPasteboard.setPasteData(pasteData); + const res8 = await systemPasteboard.hasPasteData(); + expect(res8).assertEqual(true); + systemPasteboard.getPasteData().then((data) => { + expect(data.getRecordCount()).assertEqual(1); + const primaryUri8 = data.getPrimaryUri(); + expect(primaryUri8).assertEqual(uriText8); + expect(data.hasMimeType(pasteboard.MIMETYPE_TEXT_URI)).assertEqual(true); + done(); + }); + }); + + /** + * @tc.name pasteboard_promise_test9 + * @tc.desc Adds uriText = '' + * @tc.type Function + * @tc.require AR000H5HVI + */ + it('pasteboard_promise_test9', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + await systemPasteboard.clearData(); + const uriText9 = ''; + const pasteData = pasteboard.createUriData(uriText9); + await systemPasteboard.setPasteData(pasteData); + const res9 = await systemPasteboard.hasPasteData(); + expect(res9).assertEqual(true); + systemPasteboard.getPasteData().then((data) => { + expect(data.getRecordCount()).assertEqual(1); + expect(data.getPrimaryUri()).assertEqual(uriText9); + done(); + }); + }); + + /** + * @tc.name pasteboard_promise_test10 + * @tc.desc Set uriText = 'Hello //' + * @tc.type Function + * @tc.require AR000H5HVI + */ + it('pasteboard_promise_test10', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + await systemPasteboard.clearData(); + const uriText10 = 'Hello//'; + const pasteData = pasteboard.createUriData(uriText10); + await systemPasteboard.setPasteData(pasteData); + const res10 = await systemPasteboard.hasPasteData(); + expect(res10).assertEqual(true); + systemPasteboard.getPasteData().then((data) => { + expect(data.getRecordCount()).assertEqual(1); + expect(data.hasMimeType(pasteboard.MIMETYPE_TEXT_URI)).assertEqual(true); + expect(data.getPrimaryUri()).assertEqual(uriText10); + done(); + }); + }); + + /** + * @tc.name pasteboard_promise_test11 + * @tc.desc Adds want + * @tc.type Function + * @tc.require AR000H5HVI + */ + it('pasteboard_promise_test11', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + await systemPasteboard.clearData(); + const want11 = { + bundleName: 'com.example.myapplication8', + abilityName: 'com.example.myapplication8.MainAbility', + }; + const pasteData = pasteboard.createWantData(want11); + await systemPasteboard.setPasteData(pasteData); + const res11 = await systemPasteboard.hasPasteData(); + expect(res11).assertEqual(true); + systemPasteboard.getPasteData().then((data) => { + expect(data.getRecordCount()).assertEqual(1); + const primaryWant = data.getPrimaryWant(); + expect(want11.bundleName).assertEqual(primaryWant.bundleName); + expect(want11.abilityName).assertEqual(primaryWant.abilityName); + expect(data.hasMimeType(pasteboard.MIMETYPE_TEXT_WANT)).assertEqual(true); + done(); + }); + }); + + /** + * @tc.name pasteboard_promise_test12 + * @tc.desc Adds one record(s) + * @tc.type Function + * @tc.require AR000H5HVI + */ + it('pasteboard_promise_test12', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + await systemPasteboard.clearData(); + const textData12 = 'Hello World!'; + const pasteData = pasteboard.createPlainTextData(textData12); + await systemPasteboard.setPasteData(pasteData); + const res12 = await systemPasteboard.hasPasteData(); + expect(res12).assertEqual(true); + systemPasteboard.getPasteData().then((data) => { + expect(data.getRecordCount()).assertEqual(1); + let recordText12 = data.getRecordAt(0).plainText; + expect(recordText12).assertEqual(textData12); + done(); + }); + }); + + /** + * @tc.name pasteboard_promise_test13 + * @tc.desc Adds 2 record(s) + * @tc.type Function + * @tc.require AR000H5HVI + */ + it('pasteboard_promise_test13', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + await systemPasteboard.clearData(); + const textData130 = 'Hello World!'; + const pasteData = pasteboard.createPlainTextData(textData130); + const textData131 = 'Hello World1'; + pasteData.addTextRecord(textData131); + await systemPasteboard.setPasteData(pasteData); + const res13 = await systemPasteboard.hasPasteData(); + expect(res13).assertEqual(true); + systemPasteboard.getPasteData().then((data) => { + expect(data.getRecordCount()).assertEqual(2); + const dataRecord130 = data.getRecordAt(0); + const dataRecord131 = data.getRecordAt(1); + expect(dataRecord130.plainText).assertEqual(textData131); + expect(dataRecord131.plainText).assertEqual(textData130); + done(); + }); + }); + + /** + * @tc.name pasteboard_promise_test14 + * @tc.desc Adds 15 record(s) + * @tc.type Function + * @tc.require AR000H5HVI + */ + it('pasteboard_promise_test14', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + await systemPasteboard.clearData(); + const textData140 = 'Hello World!'; + const pasteData = pasteboard.createPlainTextData(textData140); + let textData14 = ''; + for (let i = 1; i < 15; i++) { + textData14 = 'Hello World'; + textData14 = textData14 + i; + pasteData.addTextRecord(textData14); + } + await systemPasteboard.setPasteData(pasteData); + const res14 = await systemPasteboard.hasPasteData(); + expect(res14).assertEqual(true); + systemPasteboard.getPasteData().then((data) => { + expect(data.getRecordCount()).assertEqual(15); + const dataRecord14 = data.getRecordAt(14); + expect(dataRecord14.plainText).assertEqual(textData140); + done(); + }); + }); + + /** + * @tc.name pasteboard_promise_test15 + * @tc.desc Adds 30 record(s) + * @tc.type Function + * @tc.require AR000H5HVI + */ + it('pasteboard_promise_test15', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + await systemPasteboard.clearData(); + const textData150 = 'Hello World!'; + const pasteData = pasteboard.createPlainTextData(textData150); + let textData15 = ''; + for (let i = 1; i < 30; i++) { + textData15 = 'Hello World'; + textData15 = textData15 + i; + pasteData.addTextRecord(textData15); + } + await systemPasteboard.setPasteData(pasteData); + const res15 = await systemPasteboard.hasPasteData(); + expect(res15).assertEqual(true); + systemPasteboard.getPasteData().then((data) => { + expect(data.getRecordCount()).assertEqual(30); + const dataRecord15 = data.getRecordAt(0); + expect(dataRecord15.plainText).assertEqual('Hello World29'); + done(); + }); + }); + + /** + * @tc.name pasteboard_promise_test16 + * @tc.desc Adds 31 record(s) + * @tc.type Function + * @tc.require AR000H5HVI + */ + it('pasteboard_promise_test16', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + await systemPasteboard.clearData(); + const textData160 = 'Hello World!'; + const pasteData = pasteboard.createPlainTextData(textData160); + let textData16 = ''; + for (let i = 1; i < 31; i++) { + textData16 = 'Hello World'; + textData16 = textData16 + i; + pasteData.addTextRecord(textData16); + } + await systemPasteboard.setPasteData(pasteData); + const res16 = await systemPasteboard.hasPasteData(); + expect(res16).assertEqual(true); + systemPasteboard.getPasteData().then((data) => { + const recordCount16 = data.getRecordCount(); + expect(recordCount16).assertEqual(31); + const dataRecord16 = data.getRecordAt(0); + expect(dataRecord16.plainText).assertEqual('Hello World30'); + done(); + }); + }); + + /** + * @tc.name pasteboard_promise_test17 + * @tc.desc Adds PlainText,HtmlText,UriText + * @tc.type Function + * @tc.require AR000H5HVI + */ + it('pasteboard_promise_test17', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + await systemPasteboard.clearData(); + const textData17 = 'Hello World!'; + const pasteData = pasteboard.createPlainTextData(textData17); + const htmlText17 = 'Hello World!'; + pasteData.addHtmlRecord(htmlText17); + const uriText17 = 'https://www.baidu.com/'; + pasteData.addUriRecord(uriText17); + const want17 = { + bundleName: 'com.example.myapplication8', + abilityName: 'com.example.myapplication8.MainAbility', + }; + pasteData.addWantRecord(want17); + await systemPasteboard.setPasteData(pasteData); + const res17 = await systemPasteboard.hasPasteData(); + expect(res17).assertEqual(true); + systemPasteboard.getPasteData().then((data) => { + expect(data.getRecordCount()).assertEqual(4); + const wantRecord17 = data.getPrimaryWant(); + expect(wantRecord17.bundleName).assertEqual(want17.bundleName); + expect(wantRecord17.abilityName).assertEqual(want17.abilityName); + done(); + }); + }); + + /** + * @tc.name pasteboard_promise_test18 + * @tc.desc Delete one PlainTextData + * @tc.type Function + * @tc.require AR000H5HVI + */ + it('pasteboard_promise_test18', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + await systemPasteboard.clearData(); + const textData18 = 'Hello World!'; + const pasteData = pasteboard.createPlainTextData(textData18); + await systemPasteboard.setPasteData(pasteData); + const res18 = await systemPasteboard.hasPasteData(); + expect(res18).assertEqual(true); + const pasteData18 = await systemPasteboard.getPasteData(); + expect(pasteData18.getRecordCount()).assertEqual(1); + expect(pasteData18.removeRecordAt(0)).assertEqual(true); + await systemPasteboard.setPasteData(pasteData18); + systemPasteboard.getPasteData().then((data) => { + const recordCount18 = data.getRecordCount(); + expect(recordCount18).assertEqual(0); + done(); + }); + }); + + /** + * @tc.name pasteboard_promise_test19 + * @tc.desc Delete one htmlText + * @tc.type Function + * @tc.require AR000H5HVI + */ + it('pasteboard_promise_test19', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + await systemPasteboard.clearData(); + const htmlText19 = 'Hello World!'; + const pasteData = pasteboard.createHtmlData(htmlText19); + await systemPasteboard.setPasteData(pasteData); + const res19 = await systemPasteboard.hasPasteData(); + expect(res19).assertEqual(true); + const pasteData19 = await systemPasteboard.getPasteData(); + expect(pasteData19.getRecordCount()).assertEqual(1); + expect(pasteData19.removeRecordAt(0)).assertEqual(true); + await systemPasteboard.setPasteData(pasteData19); + systemPasteboard.getPasteData().then((data) => { + const recordCount19 = data.getRecordCount(); + expect(recordCount19).assertEqual(0); + done(); + }); + }); + + /** + * @tc.name pasteboard_promise_test20 + * @tc.desc Delete one uriText + * @tc.type Function + * @tc.require AR000H5HVI + */ + it('pasteboard_promise_test20', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + await systemPasteboard.clearData(); + const uriText20 = 'https://www.baidu.com/'; + const pasteData = pasteboard.createUriData(uriText20); + await systemPasteboard.setPasteData(pasteData); + const res20 = await systemPasteboard.hasPasteData(); + expect(res20).assertEqual(true); + const pasteData20 = await systemPasteboard.getPasteData(); + expect(pasteData20.getRecordCount()).assertEqual(1); + expect(pasteData20.removeRecordAt(0)).assertEqual(true); + await systemPasteboard.setPasteData(pasteData20); + systemPasteboard.getPasteData().then((data) => { + const recordCount20 = data.getRecordCount(); + expect(recordCount20).assertEqual(0); + done(); + }); + }); + + /** + * @tc.name pasteboard_promise_test21 + * @tc.desc Delete one want + * @tc.type Function + * @tc.require AR000H5I1D + */ + it('pasteboard_promise_test21', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + await systemPasteboard.clearData(); + const want21 = { + bundleName: 'com.example.myapplication8', + abilityName: 'com.example.myapplication8.MainAbility', + }; + const pasteData = pasteboard.createWantData(want21); + await systemPasteboard.setPasteData(pasteData); + const res21 = await systemPasteboard.hasPasteData(); + expect(res21).assertEqual(true); + const pasteData21 = await systemPasteboard.getPasteData(); + expect(pasteData21.getRecordCount()).assertEqual(1); + expect(pasteData21.removeRecordAt(0)).assertEqual(true); + await systemPasteboard.setPasteData(pasteData21); + systemPasteboard.getPasteData().then((data) => { + const recordCount21 = data.getRecordCount(); + expect(recordCount21).assertEqual(0); + done(); + }); + }); + + /** + * @tc.name pasteboard_promise_test22 + * @tc.desc Deletes 300K PlainTextData + * @tc.type Function + * @tc.require AR000H5I1D + */ + it('pasteboard_promise_test22', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + await systemPasteboard.clearData(); + let textData22 = ''; + for (let i = 0; i < 300; i++) { + textData22 = textData22 + 'A'; + } + const pasteData = pasteboard.createPlainTextData(textData22); + await systemPasteboard.setPasteData(pasteData); + const res22 = await systemPasteboard.hasPasteData(); + expect(res22).assertEqual(true); + const pasteData22 = await systemPasteboard.getPasteData(); + expect(pasteData22.getRecordCount()).assertEqual(1); + expect(pasteData22.removeRecordAt(0)).assertEqual(true); + await systemPasteboard.setPasteData(pasteData22); + systemPasteboard.getPasteData().then((data) => { + const recordCount22 = data.getRecordCount(); + expect(recordCount22).assertEqual(0); + done(); + }); + }); + + /** + * @tc.name pasteboard_promise_test23 + * @tc.desc Deletes 30 record(s) + * @tc.type Function + * @tc.require AR000H5I1D + */ + it('pasteboard_promise_test23', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + await systemPasteboard.clearData(); + const textData230 = 'Hello World'; + const pasteData = pasteboard.createPlainTextData(textData230); + let textData23 = ''; + for (let i = 1; i < 30; i++) { + textData23 = 'Hello World'; + textData23 = textData23 + i; + pasteData.addTextRecord(textData23); + } + await systemPasteboard.setPasteData(pasteData); + const res23 = await systemPasteboard.hasPasteData(); + expect(res23).assertEqual(true); + const pasteData23 = await systemPasteboard.getPasteData(); + expect(pasteData23.getRecordCount()).assertEqual(30); + for (let i = 0; i < 30; i++) { + expect(pasteData23.removeRecordAt(0)).assertEqual(true); + } + expect(pasteData23.getRecordCount()).assertEqual(0); + systemPasteboard.setPasteData(pasteData23).then(() => { + systemPasteboard.getPasteData().then((data) => { + let recordCount23 = data.getRecordCount(); + expect(recordCount23).assertEqual(0); + done(); + }); + }); + }); + + /** + * @tc.name pasteboard_promise_test24 + * @tc.desc Deletes replaced record + * @tc.type Function + * @tc.require AR000H5I1D + */ + it('pasteboard_promise_test24', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + await systemPasteboard.clearData(); + const textData24 = 'Hello World!'; + const pasteData = pasteboard.createPlainTextData(textData24); + await systemPasteboard.setPasteData(pasteData); + const res24 = await systemPasteboard.hasPasteData(); + expect(res24).assertEqual(true); + const pasteData24 = await systemPasteboard.getPasteData(); + expect(pasteData24.getRecordCount()).assertEqual(1); + const textData241 = 'Hello World1'; + const pasteDataRecord = pasteboard.createPlainTextRecord(textData241); + const replace = pasteData24.replaceRecordAt(0, pasteDataRecord); + expect(replace).assertEqual(true); + const primaryText = pasteData24.getPrimaryText(); + expect(primaryText).assertEqual(textData241); + expect(pasteData24.hasMimeType(pasteboard.MIMETYPE_TEXT_PLAIN)).assertEqual(true); + const dataRecord = pasteData24.getRecordAt(0); + expect(dataRecord.plainText).assertEqual(textData241); + expect(pasteData24.removeRecordAt(0)).assertEqual(true); + systemPasteboard.setPasteData(pasteData24).then(() => { + systemPasteboard.getPasteData().then((data) => { + const recordCount24 = data.getRecordCount(); + expect(recordCount24).assertEqual(0); + done(); + }); + }); + }); + + /** + * @tc.name pasteboard_promise_test25 + * @tc.desc Deletes 文本、uri、html + * @tc.type Function + * @tc.require AR000H5I1D + */ + it('pasteboard_promise_test25', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + await systemPasteboard.clearData(); + const textData25 = 'Hello World!'; + const pasteData = pasteboard.createPlainTextData(textData25); + const htmlText25 = 'Hello World!'; + pasteData.addHtmlRecord(htmlText25); + const uriText25 = 'https://www.baidu.com/'; + pasteData.addUriRecord(uriText25); + await systemPasteboard.setPasteData(pasteData); + const res25 = await systemPasteboard.hasPasteData(); + expect(res25).assertEqual(true); + const pasteData25 = await systemPasteboard.getPasteData(); + expect(pasteData25.getRecordCount()).assertEqual(3); + expect(pasteData25.removeRecordAt(0)).assertEqual(true); + expect(pasteData25.removeRecordAt(0)).assertEqual(true); + expect(pasteData25.removeRecordAt(0)).assertEqual(true); + systemPasteboard.setPasteData(pasteData25).then(() => { + systemPasteboard.getPasteData().then((data) => { + const recordCount25 = data.getRecordCount(); + expect(recordCount25).assertEqual(0); + done(); + }); + }); + }); + + /** + * @tc.name pasteboard_promise_test26 + * @tc.desc Replaces 文本 record + * @tc.type Function + * @tc.require AR000H5I1D + */ + it('pasteboard_promise_test26', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + await systemPasteboard.clearData(); + const textData26 = 'Hello World!'; + const pasteData = pasteboard.createPlainTextData(textData26); + await systemPasteboard.setPasteData(pasteData); + const res26 = await systemPasteboard.hasPasteData(); + expect(res26).assertEqual(true); + systemPasteboard.getPasteData().then((data) => { + const pasteData26 = data; + expect(pasteData26.getRecordCount()).assertEqual(1); + const textData261 = 'Hello World1'; + const pasteDataRecord = pasteboard.createPlainTextRecord(textData261); + const replace26 = pasteData26.replaceRecordAt(0, pasteDataRecord); + expect(replace26).assertEqual(true); + const primaryText26 = pasteData26.getPrimaryText(); + expect(primaryText26).assertEqual(textData261); + done(); + }); + }); + + /** + * @tc.name pasteboard_promise_test27 + * @tc.desc Replaces htmlText record + * @tc.type Function + * @tc.require AR000H5I1D + */ + it('pasteboard_promise_test27', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + await systemPasteboard.clearData(); + const htmlText27 = 'Hello World!'; + const pasteData = pasteboard.createHtmlData(htmlText27); + await systemPasteboard.setPasteData(pasteData); + const res27 = await systemPasteboard.hasPasteData(); + expect(res27).assertEqual(true); + systemPasteboard.getPasteData().then((data) => { + const pasteData27 = data; + expect(pasteData27.getRecordCount()).assertEqual(1); + const htmlText27 = 'Hello World 1'; + const pasteDataRecord = pasteboard.createHtmlTextRecord(htmlText27); + const replace27 = pasteData27.replaceRecordAt(0, pasteDataRecord); + expect(replace27).assertEqual(true); + const primaryHtml271 = pasteData27.getPrimaryHtml(); + expect(primaryHtml271).assertEqual(htmlText27); + expect(pasteData27.hasMimeType(pasteboard.MIMETYPE_TEXT_HTML)).assertEqual(true); + const primaryHtml272 = pasteData27.getPrimaryHtml(); + expect(primaryHtml272).assertEqual(htmlText27); + done(); + }); + }); + + /** + * @tc.name pasteboard_promise_test28 + * @tc.desc Replaces uri record + * @tc.type Function + * @tc.require AR000H5I1D + */ + it('pasteboard_promise_test28', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + await systemPasteboard.clearData(); + const uriText28 = 'https://www.baidu.com/'; + const pasteData = pasteboard.createUriData(uriText28); + await systemPasteboard.setPasteData(pasteData); + const res28 = await systemPasteboard.hasPasteData(); + expect(res28).assertEqual(true); + systemPasteboard.getPasteData().then((data) => { + const pasteData28 = data; + expect(pasteData28.getRecordCount()).assertEqual(1); + const uriText281 = 'https://www.baidu.com/1'; + const pasteDataRecord = pasteboard.createUriRecord(uriText281); + const replace28 = pasteData28.replaceRecordAt(0, pasteDataRecord); + expect(replace28).assertEqual(true); + const primaryUri1 = pasteData28.getPrimaryUri(); + expect(primaryUri1).assertEqual(uriText281); + expect(pasteData28.hasMimeType(pasteboard.MIMETYPE_TEXT_URI)).assertEqual(true); + const primaryUri2 = pasteData28.getPrimaryUri(); + expect(primaryUri2).assertEqual(uriText281); + done(); + }); + }); + + /** + * @tc.name pasteboard_promise_test29 + * @tc.desc Replaces want record + * @tc.type Function + * @tc.require AR000H5I1D + */ + it('pasteboard_promise_test29', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + await systemPasteboard.clearData(); + const wantText29 = { + bundleName: 'com.example.myapplication3', + abilityName: 'com.example.myapplication3.MainAbility', + }; + const pasteData = pasteboard.createData(pasteboard.MIMETYPE_TEXT_WANT, wantText29); + await systemPasteboard.setPasteData(pasteData); + const res29 = await systemPasteboard.hasPasteData(); + expect(res29).assertEqual(true); + systemPasteboard.getPasteData().then((data) => { + const pasteData29 = data; + expect(pasteData29.getRecordCount()).assertEqual(1); + const wantText291 = { + bundleName: 'com.example.myapplication30', + abilityName: 'com.example.myapplication30.MainAbility', + }; + const pasteDataRecord = pasteboard.createRecord(pasteboard.MIMETYPE_TEXT_WANT, wantText291); + const replace29 = pasteData29.replaceRecordAt(0, pasteDataRecord); + expect(replace29).assertEqual(true); + const primaryWant29 = pasteData29.getPrimaryWant(); + expect(primaryWant29.bundleName).assertEqual(wantText291.bundleName); + expect(primaryWant29.abilityName).assertEqual(wantText291.abilityName); + done(); + }); + }); + + /** + * @tc.name pasteboard_promise_test30 + * @tc.desc Replaces 300k文本 record + * @tc.type Function + * @tc.require AR000H5I1D + */ + it('pasteboard_promise_test30', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + await systemPasteboard.clearData(); + let textData30 = ''; + for (let i = 0; i < 300; i++) { + textData30 = textData30 + 'A'; + } + const pasteData = pasteboard.createPlainTextData(textData30); + await systemPasteboard.setPasteData(pasteData); + const res30 = await systemPasteboard.hasPasteData(); + expect(res30).assertEqual(true); + systemPasteboard.getPasteData().then((data) => { + const pasteData30 = data; + expect(pasteData30.getRecordCount()).assertEqual(1); + const textData301 = 'Hello World1'; + const pasteDataRecord = pasteboard.createPlainTextRecord(textData301); + const replace = pasteData30.replaceRecordAt(0, pasteDataRecord); + expect(replace).assertEqual(true); + const primaryText = pasteData30.getPrimaryText(); + expect(primaryText).assertEqual(textData301); + done(); + }); + }); + + /** + * @tc.name pasteboard_promise_test31 + * @tc.desc Clears pasteBoard, gets record count + * @tc.type Function + * @tc.require AR000H5I1D + */ + it('pasteboard_promise_test31', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + await systemPasteboard.clearData(); + const textData31 = 'Hello World!'; + const pasteData = pasteboard.createPlainTextData(textData31); + await systemPasteboard.setPasteData(pasteData); + const res31 = await systemPasteboard.hasPasteData(); + expect(res31).assertEqual(true); + const pasteData31 = await systemPasteboard.getPasteData(); + expect(pasteData31.getRecordCount()).assertEqual(1); + await systemPasteboard.clearData(); + systemPasteboard.getPasteData().then((data) => { + const pasteData2 = data; + const recordCount = pasteData2.getRecordCount(); + expect(recordCount).assertEqual(0); + done(); + }); + }); + + /** + * @tc.name pasteboard_promise_test32 + * @tc.desc Adds Property + * @tc.type Function + * @tc.require AR000H5I1D + */ + it('pasteboard_promise_test32', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + await systemPasteboard.clearData(); + const textData32 = 'Hello World!'; + const pasteData = pasteboard.createPlainTextData(textData32); + await systemPasteboard.setPasteData(pasteData); + const res32 = await systemPasteboard.hasPasteData(); + expect(res32).assertEqual(true); + const pasteData32 = await systemPasteboard.getPasteData(); + expect(pasteData32.getRecordCount()).assertEqual(1); + const pasteDataProperty = pasteData32.getProperty(); + expect(pasteDataProperty.shareOption).assertEqual(pasteboard.ShareOption.CrossDevice); + pasteDataProperty.shareOption = pasteboard.ShareOption.InApp; + pasteData32.setProperty(pasteDataProperty); + expect(pasteData32.getProperty().shareOption).assertEqual(pasteboard.ShareOption.InApp); + done(); + }); + + /** + * @tc.name pasteboard_promise_test33 + * @tc.desc Clears pasteBoard and check property + * @tc.type Function + * @tc.require AR000H5I1D + */ + it('pasteboard_promise_test33', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + await systemPasteboard.clearData(); + const textData33 = 'Hello World!'; + const pasteData = pasteboard.createPlainTextData(textData33); + await systemPasteboard.setPasteData(pasteData); + const res33 = await systemPasteboard.hasPasteData(); + expect(res33).assertEqual(true); + systemPasteboard.getPasteData().then(async (data) => { + expect(data.getRecordCount()).assertEqual(1); + await systemPasteboard.clearData(); + const newPasteData = await systemPasteboard.getPasteData(); + expect(newPasteData.getProperty().shareOption).assertEqual(pasteboard.ShareOption.CrossDevice); + done(); + }); + }); + + /** + * @tc.name pasteboard_promise_test34 + * @tc.desc 打开内容变化通知功能 + * @tc.type Function + * @tc.require AR000H5I1D + */ + it('pasteboard_promise_test34', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + await systemPasteboard.clearData(); + systemPasteboard.on('update', contentChanges); + const textData34 = 'Hello World!'; + const pasteData = pasteboard.createPlainTextData(textData34); + await systemPasteboard.setPasteData(pasteData); + const res34 = await systemPasteboard.hasPasteData(); + expect(res34).assertEqual(true); + systemPasteboard.getPasteData().then((data) => { + expect(data.getRecordCount()).assertEqual(1); + expect(data.removeRecordAt(0)).assertEqual(true); + expect(data.getRecordCount()).assertEqual(0); + done(); + }); + }); + + /** + * @tc.name pasteboard_promise_test35 + * @tc.desc 清除剪切板内的文本数据项 + * @tc.type Function + * @tc.require AR000H5I1D + */ + it('pasteboard_promise_test35', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + await systemPasteboard.clearData(); + const textData35 = 'Hello World!'; + const pasteData = pasteboard.createPlainTextData(textData35); + await systemPasteboard.setPasteData(pasteData); + const res35 = await systemPasteboard.hasPasteData(); + expect(res35).assertEqual(true); + const pasteData35 = await systemPasteboard.getPasteData(); + expect(pasteData35.getRecordCount()).assertEqual(1); + await systemPasteboard.clearData(); + systemPasteboard.getPasteData().then((data) => { + const recordCount35 = data.getRecordCount(); + expect(recordCount35).assertEqual(0); + done(); + }); + }); + + /** + * @tc.name pasteboard_promise_test36 + * @tc.desc 清除剪切板内的uri数据项 + * @tc.type Function + * @tc.require AR000H5I1D + */ + it('pasteboard_promise_test36', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + await systemPasteboard.clearData(); + const uriText36 = 'https://www.baidu.com/'; + const pasteData = pasteboard.createUriData(uriText36); + await systemPasteboard.setPasteData(pasteData); + const res36 = await systemPasteboard.hasPasteData(); + expect(res36).assertEqual(true); + const pasteData36 = await systemPasteboard.getPasteData(); + expect(pasteData36.getRecordCount()).assertEqual(1); + await systemPasteboard.clearData(); + systemPasteboard.getPasteData().then((data) => { + const recordCount36 = data.getRecordCount(); + expect(recordCount36).assertEqual(0); + done(); + }); + }); + + /** + * @tc.name pasteboard_promise_test37 + * @tc.desc 清除剪切板内的html数据项 + * @tc.type Function + * @tc.require AR000H5I1D + */ + it('pasteboard_promise_test37', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + await systemPasteboard.clearData(); + const htmlText37 = 'Hello World!'; + const pasteData = pasteboard.createHtmlData(htmlText37); + await systemPasteboard.setPasteData(pasteData); + const res37 = await systemPasteboard.hasPasteData(); + expect(res37).assertEqual(true); + const pasteData37 = await systemPasteboard.getPasteData(); + expect(pasteData37.getRecordCount()).assertEqual(1); + await systemPasteboard.clearData(); + systemPasteboard.getPasteData().then((data) => { + const recordCount37 = data.getRecordCount(); + expect(recordCount37).assertEqual(0); + done(); + }); + }); + + /** + * @tc.name pasteboard_promise_test38 + * @tc.desc 清除剪切板内的want数据项 + * @tc.type Function + * @tc.require AR000H5I1D + */ + it('pasteboard_promise_test38', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + await systemPasteboard.clearData(); + const myWant38 = { + bundleName: 'com.example.myapplication55', + abilityName: 'com.example.myapplication55.MainAbility', + }; + const pasteData381 = pasteboard.createWantData(myWant38); + await systemPasteboard.setPasteData(pasteData381); + const res38 = await systemPasteboard.hasPasteData(); + expect(res38).assertEqual(true); + const pasteData38 = await systemPasteboard.getPasteData(); + expect(pasteData38.getRecordCount()).assertEqual(1); + await systemPasteboard.clearData(); + systemPasteboard.getPasteData().then((data) => { + const recordCount38 = data.getRecordCount(); + expect(recordCount38).assertEqual(0); + done(); + }); + }); + + /** + * @tc.name pasteboard_promise_test39 + * @tc.desc 向剪切板内增加30条数据项,然后清除 + * @tc.type Function + * @tc.require AR000H5I1D + */ + it('pasteboard_promise_test39', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + await systemPasteboard.clearData(); + const textData390 = 'Hello World!'; + const pasteData = pasteboard.createPlainTextData(textData390); + let textData39 = ''; + for (let i = 1; i < 30; i++) { + textData39 = 'Hello World'; + textData39 = textData39 + i; + pasteData.addTextRecord(textData39); + } + await systemPasteboard.setPasteData(pasteData); + const res39 = await systemPasteboard.hasPasteData(); + expect(res39).assertEqual(true); + const pasteData39 = await systemPasteboard.getPasteData(); + expect(pasteData39.getRecordCount()).assertEqual(30); + await systemPasteboard.clearData(); + systemPasteboard.getPasteData().then((data) => { + const recordCount39 = data.getRecordCount(); + expect(recordCount39).assertEqual(0); + done(); + }); + }); + + /** + * @tc.name pasteboard_promise_test40 + * @tc.desc 向剪贴板数据各增加5条文本、uri、html数据,然后清除 + * @tc.type Function + * @tc.require AR000H5I1D + */ + it('pasteboard_promise_test40', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + await systemPasteboard.clearData(); + const textData400 = 'Hello World0'; + const pasteData = pasteboard.createPlainTextData(textData400); + let textData40 = ''; + for (let i = 1; i < 5; i++) { + textData40 = 'Hello World'; + textData40 = textData40 + i; + pasteData.addTextRecord(textData40); + } + let htmlText40 = ''; + for (let i = 0; i < 5; i++) { + htmlText40 = 'Hello World!'; + htmlText40 = htmlText40 + i; + pasteData.addHtmlRecord(htmlText40); + } + let uriText40 = ''; + for (let i = 0; i < 5; i++) { + uriText40 = 'https://www.baidu.com/'; + uriText40 = uriText40 + i; + pasteData.addUriRecord(uriText40); + } + await systemPasteboard.setPasteData(pasteData); + const res40 = await systemPasteboard.hasPasteData(); + expect(res40).assertEqual(true); + const data40 = await systemPasteboard.getPasteData(); + expect(data40.getRecordCount()).assertEqual(15); + await systemPasteboard.clearData(); + systemPasteboard.getPasteData().then((data) => { + const recordCount40 = data.getRecordCount(); + expect(recordCount40).assertEqual(0); + done(); + }); + }); + + /** + * @tc.name pasteboard_promise_test41 + * @tc.desc 更新剪贴板数据,查询剪贴板存在剪贴板数据 + * @tc.type Function + * @tc.require AR000HEECD + */ + it('pasteboard_promise_test41', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + await systemPasteboard.clearData(); + const textData41 = 'Hello World!'; + const pasteData = pasteboard.createPlainTextData(textData41); + await systemPasteboard.setPasteData(pasteData); + const res41 = await systemPasteboard.hasPasteData(); + expect(res41).assertEqual(true); + const pasteData41 = await systemPasteboard.getPasteData(); + expect(pasteData41.getRecordCount()).assertEqual(1); + const textData411 = 'Hello World1'; + const pasteDataRecord = pasteboard.createPlainTextRecord(textData411); + const replace41 = pasteData41.replaceRecordAt(0, pasteDataRecord); + expect(replace41).assertEqual(true); + await systemPasteboard.setPasteData(pasteData41); + systemPasteboard.hasPasteData().then(async (data) => { + expect(data).assertEqual(true); + const newData41 = await systemPasteboard.getPasteData(); + expect(newData41.getPrimaryText()).assertEqual(textData411); + const newPasteDataRecord = newData41.getRecordAt(0); + expect(newPasteDataRecord.plainText).assertEqual(textData411); + done(); + }); + }); + + /** + * @tc.name pasteboard_promise_test42 + * @tc.desc 删除所有的剪贴板数据,查询剪贴板不存在剪贴板数据 + * @tc.type Function + * @tc.require AR000HEECD + */ + it('pasteboard_promise_test42', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + await systemPasteboard.clearData(); + const textData42 = 'Hello World!'; + const data42 = pasteboard.createPlainTextData(textData42); + await systemPasteboard.setPasteData(data42); + const res42 = await systemPasteboard.hasPasteData(); + expect(res42).assertEqual(true); + const pasteData42 = await systemPasteboard.getPasteData(); + const recordCount = pasteData42.getRecordCount(); + expect(recordCount).assertEqual(1); + expect(pasteData42.removeRecordAt(0)).assertEqual(true); + expect(pasteData42.getRecordCount()).assertEqual(0); + const newData42 = await systemPasteboard.getPasteData(); + expect(newData42.getRecordCount()).assertEqual(1); + done(); + }); + + /** + * @tc.name pasteboard_promise_test43 + * @tc.desc 将文本数据强制转换为文本 + * @tc.type Function + * @tc.require AR000HEECD + */ + it('pasteboard_promise_test43', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + await systemPasteboard.clearData(); + const textData43 = 'Hello World!'; + const pasteData = pasteboard.createPlainTextData(textData43); + await systemPasteboard.setPasteData(pasteData); + const res43 = await systemPasteboard.hasPasteData(); + expect(res43).assertEqual(true); + systemPasteboard.getPasteData().then(async (data) => { + const pasteData143 = data; + expect(pasteData143.getRecordCount()).assertEqual(1); + const pasteDataRecord = pasteData143.getRecordAt(0); + const text43 = await pasteDataRecord.convertToText(); + expect(text43).assertEqual(textData43); + done(); + }); + }); + + /** + * @tc.name pasteboard_promise_test44 + * @tc.desc 将一条含有特殊字符、中英混杂的文本数据强制转换为文本 + * @tc.type Function + * @tc.require AR000HEECD + */ + it('pasteboard_promise_test44', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + await systemPasteboard.clearData(); + const textData44 = 'Hello 中国!@#$%^&*()_+{}?.'; + const pasteData = pasteboard.createPlainTextData(textData44); + await systemPasteboard.setPasteData(pasteData); + const res44 = await systemPasteboard.hasPasteData(); + expect(res44).assertEqual(true); + const pasteData44 = await systemPasteboard.getPasteData(); + expect(pasteData44.getRecordCount()).assertEqual(1); + const pasteDataRecord = pasteData44.getRecordAt(0); + pasteDataRecord.convertToText((err, text) => { + if (err) { + console.info('f_test44 pasteDataRecord.convertToText error: ' + error); + } else { + expect(textData44).assertEqual(text); + done(); + } + }); + }); + + /** + * @tc.name pasteboard_promise_test45 + * @tc.desc 将一条超长文本数据 (大小为301K)强制转换为文本 + * @tc.type Function + * @tc.require AR000HEECD + */ + it('pasteboard_promise_test45', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + await systemPasteboard.clearData(); + let textData45 = ''; + for (let i = 0; i < 301; i++) { + textData45 = textData45 + 'A'; + } + const pasteData = pasteboard.createPlainTextData(textData45); + await systemPasteboard.setPasteData(pasteData); + const res45 = await systemPasteboard.hasPasteData(); + expect(res45).assertEqual(true); + const pasteData45 = await systemPasteboard.getPasteData(); + expect(pasteData45.getRecordCount()).assertEqual(1); + const pasteDataRecord = pasteData45.getRecordAt(0); + pasteDataRecord.convertToText((err, text) => { + if (err) { + console.info('f_test45 pasteDataRecord.convertToText error: ' + error); + } else { + expect(textData45).assertEqual(text); + done(); + } + }); + }); + + /** + * @tc.name pasteboard_promise_test46 + * @tc.desc 将uri数据强制转换为文本 + * @tc.type Function + * @tc.require AR000HEECD + */ + it('pasteboard_promise_test46', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + await systemPasteboard.clearData(); + const uriText46 = 'https://www.baidu.com/'; + const pasteData = pasteboard.createUriData(uriText46); + await systemPasteboard.setPasteData(pasteData); + const res46 = await systemPasteboard.hasPasteData(); + expect(res46).assertEqual(true); + let pasteData46 = await systemPasteboard.getPasteData(); + expect(pasteData46.getRecordCount()).assertEqual(1); + let pasteDataRecord = pasteData46.getRecordAt(0); + pasteDataRecord + .convertToText() + .then((text) => { + expect(uriText46).assertEqual(text); + done(); + }) + .catch((error) => { + console.info('f_test46 pasteDataRecord.convertToText error: ' + error); + }); + }); + + /** + * @tc.name pasteboard_promise_test47 + * @tc.desc 复制文本、uri格式 + * @tc.type Function + * @tc.require AR000HEECD + */ + it('pasteboard_promise_test47', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + await systemPasteboard.clearData(); + const textData470 = 'Hello World0'; + const pasteData = pasteboard.createPlainTextData(textData470); + const uriText47 = pasteboard.createUriRecord('https://www.baidu.com/'); + pasteData.addRecord(uriText47); + await systemPasteboard.setPasteData(pasteData); + const res47 = await systemPasteboard.hasPasteData(); + expect(res47).assertEqual(true); + systemPasteboard.getPasteData().then((data) => { + const recordCount47 = data.getRecordCount(); + expect(recordCount47).assertEqual(2); + const pasteDataRecord1 = data.getRecordAt(0); + const pasteDataRecord2 = data.getRecordAt(1); + expect(pasteDataRecord1.uri).assertEqual(uriText47.uri); + expect(pasteDataRecord2.plainText).assertEqual(textData470); + done(); + }); + }); + + /** + * @tc.name pasteboard_promise_test48 + * @tc.desc 关闭内容变化通知功能:向剪贴板数据增加、删除等html数据项 + * @tc.type Function + * @tc.require AR000HEECD + */ + it('pasteboard_promise_test48', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + await systemPasteboard.clearData(); + systemPasteboard.off('update', contentChanges); + const htmlText48 = 'Hello World!'; + const pasteData = pasteboard.createHtmlData(htmlText48); + await systemPasteboard.setPasteData(pasteData); + const res48 = await systemPasteboard.hasPasteData(); + expect(res48).assertEqual(true); + systemPasteboard.getPasteData().then((data) => { + expect(data.getRecordCount()).assertEqual(1); + expect(data.removeRecordAt(0)).assertEqual(true); + expect(data.getRecordCount()).assertEqual(0); + done(); + }); + }); + + /** + * @tc.name pasteboard_promise_test49 + * @tc.desc 创建pixelMap + * @tc.type Function + * @tc.require AR000HEECD + */ + it('pasteboard_promise_test49', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + await systemPasteboard.clearData(); + const buffer49 = new ArrayBuffer(128); + const opt49 = { + size: { height: 5, width: 5 }, + pixelFormat: 3, + editable: true, + alphaType: 1, + scaleMode: 1, + }; + const pixelMap = await image.createPixelMap(buffer49, opt49); + expect(pixelMap.getPixelBytesNumber()).assertEqual(100); + const pasteData49 = pasteboard.createData(pasteboard.MIMETYPE_PIXELMAP, pixelMap); + await systemPasteboard.setPasteData(pasteData49); + const res49 = await systemPasteboard.hasPasteData(); + expect(res49).assertEqual(true); + systemPasteboard.getPasteData().then(async (newPasteData) => { + const recordCount49 = newPasteData.getRecordCount(); + expect(recordCount49).assertEqual(1); + const newPixelMap49 = newPasteData.getPrimaryPixelMap(); + const PixelMapBytesNumber = newPixelMap49.getPixelBytesNumber(); + expect(PixelMapBytesNumber).assertEqual(100); + const imageInfo = await newPixelMap49.getImageInfo(); + expect(imageInfo.size.height === 5 && imageInfo.size.width === 5).assertEqual(true); + done(); + }); + }); + + /** + * @tc.name pasteboard_promise_test50 + * @tc.desc 创建kv Record + * @tc.type Function + * @tc.require AR000HEECD + */ + it('pasteboard_promise_test50', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + await systemPasteboard.clearData(); + const dataXml50 = new ArrayBuffer(512); + let int32view50 = new Int32Array(dataXml50); + for (let i = 0; i < int32view50.length; i++) { + int32view50[i] = 65535 + i; + } + const pasteDataRecord = pasteboard.createRecord('app/xml', dataXml50); + const dataJpg50 = new ArrayBuffer(256); + pasteDataRecord.data['image/ipg'] = dataJpg50; + const pasteData50 = pasteboard.createHtmlData('application/xml'); + const replace = pasteData50.replaceRecordAt(0, pasteDataRecord); + expect(replace).assertEqual(true); + await systemPasteboard.setPasteData(pasteData50); + const res50 = await systemPasteboard.hasPasteData(); + expect(res50).assertEqual(true); + systemPasteboard.getPasteData().then((newPasteData) => { + const recordCount50 = newPasteData.getRecordCount(); + expect(recordCount50).assertEqual(1); + let newPasteDataRecord = newPasteData.getRecordAt(0); + let newAppXml50 = newPasteDataRecord.data['app/xml']; + let newImageIpg50 = newPasteDataRecord.data['image/ipg']; + expect(newAppXml50.byteLength === 512 && newImageIpg50.byteLength === 256).assertEqual(true); + let newAppXmlView50 = new Int32Array(newAppXml50); + let newImageIpgView50 = new Int32Array(newImageIpg50); + for (let i = 0; i < newAppXmlView50.length; i++) { + console.info('newAppXml[' + i + '] = ' + newAppXmlView50[i]); + } + for (let i = 0; i < newImageIpgView50.length; i++) { + console.info('newImageIpg[' + i + '] = ' + newImageIpg50[i]); + } + done(); + }); + }); + + /** + * @tc.name pasteboard_promise_test51 + * @tc.desc 测试addPixelMapRecord + * @tc.type Function + * @tc.require AR000HEECD + */ + it('pasteboard_promise_test51', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + await systemPasteboard.clearData(); + const buffer51 = new ArrayBuffer(128); + const opt51 = { + size: { height: 5, width: 5 }, + pixelFormat: 3, + editable: true, + alphaType: 1, + scaleMode: 1, + }; + const pasteData51 = pasteboard.createHtmlData('application/xml'); + const pixelMap = await image.createPixelMap(buffer51, opt51); + expect(pixelMap.getPixelBytesNumber() === 100).assertEqual(true); + pasteData51.addRecord(pasteboard.MIMETYPE_PIXELMAP, pixelMap); + await systemPasteboard.setPasteData(pasteData51); + const res51 = await systemPasteboard.hasPasteData(); + expect(res51).assertEqual(true); + systemPasteboard.getPasteData().then(async (newPasteData) => { + const recordCount51 = newPasteData.getRecordCount(); + expect(recordCount51).assertEqual(2); + const newPixelMap51 = newPasteData.getPrimaryPixelMap(); + const PixelMapBytesNumber51 = newPixelMap51.getPixelBytesNumber(); + expect(PixelMapBytesNumber51).assertEqual(100); + const newHtmlData51 = newPasteData.getRecordAt(1); + expect(newHtmlData51.htmlText).assertEqual('application/xml'); + const imageInfo51 = await newPixelMap51.getImageInfo(); + expect(imageInfo51.size.height === 5 && imageInfo51.size.width === 5).assertEqual(true); + done(); + }); + }); + + /** + * @tc.name pasteboard_promise_test52 + * @tc.desc 支持512个record + * @tc.type Function + * @tc.require AR000HEECB + */ + it('pasteboard_promise_test52', 0, async function (done) { + const systemPasteboard = pasteboard.getSystemPasteboard(); + await systemPasteboard.clearData(); + const dataHtml52 = new ArrayBuffer(256); + const htmlText52 = 'Hello!'; + const uriText52 = 'https://www.baidu.com/'; + const wantText52 = { + bundleName: 'com.example.myapplication3', + abilityName: 'com.example.myapplication3.MainAbility', + }; + const plainText52 = ''; + const pasteData52 = pasteboard.createData('x'.repeat(1024), dataHtml52); + const record52 = pasteData52.getRecordAt(0); + record52.htmlText = htmlText52; + record52.plainText = plainText52; + record52.uri = uriText52; + record52.want = wantText52; + const buffer52 = new ArrayBuffer(128); + const opt52 = { + size: { height: 5, width: 5 }, + pixelFormat: 3, + editable: true, + alphaType: 1, + scaleMode: 1, + }; + const pixelMap = await image.createPixelMap(buffer52, opt52); + record52.pixelMap = pixelMap; + pasteData52.replaceRecordAt(0, record52); + for (let i = 0; i < 511; i++) { + pasteData52.addRecord(record52); + } + await systemPasteboard.setPasteData(pasteData52); + const res52 = await systemPasteboard.hasPasteData(); + expect(res52).assertTrue(); + systemPasteboard.getPasteData().then((data) => { + expect(data.getRecordCount()).assertEqual(512); + expect(data.getRecordAt(0).mimeType).assertEqual('x'.repeat(1024)); + expect(data.getPrimaryWant().bundleName).assertEqual(wantText52.bundleName); + expect(data.getRecordAt(253).htmlText).assertEqual(htmlText52); + expect(data.getRecordAt(511).plainText).assertEqual(plainText52); + done(); + }); + }); + + /** + * The callback function is used for pasteboard content changes + */ + function contentChanges() { + console.info('#EVENT: The content is changed in the pasteboard'); + } +}); diff --git a/pasteboard/interfaces/kits/napi/test/unittest/pasteboardperf/BUILD.gn b/pasteboard/interfaces/kits/napi/test/unittest/pasteboardperf/BUILD.gn new file mode 100644 index 00000000..b905f86d --- /dev/null +++ b/pasteboard/interfaces/kits/napi/test/unittest/pasteboardperf/BUILD.gn @@ -0,0 +1,29 @@ +# Copyright (C) 2022-2023 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") + +module_output_path = "distributeddatamgr/pasteboard" + +ohos_js_unittest("PasteBoardPerfJSTest") { + module_out_path = module_output_path + + hap_profile = "../config.json" + + certificate_profile = "../openharmony_sx.p7b" +} + +group("unittest") { + testonly = true + deps = [ ":PasteBoardPerfJSTest" ] +} diff --git a/pasteboard/interfaces/kits/napi/test/unittest/pasteboardperf/PasteBoardCallbackApiPerfJsunit.test.js b/pasteboard/interfaces/kits/napi/test/unittest/pasteboardperf/PasteBoardCallbackApiPerfJsunit.test.js new file mode 100644 index 00000000..2d73ff04 --- /dev/null +++ b/pasteboard/interfaces/kits/napi/test/unittest/pasteboardperf/PasteBoardCallbackApiPerfJsunit.test.js @@ -0,0 +1,275 @@ +/* + * Copyright (C) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the 'License'); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an 'AS IS' BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// @ts-nocheck +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from 'deccjsunit/index'; +import pasteboard from '@ohos.pasteboard'; +import image from '@ohos.multimedia.image'; + +describe('PasteBoardPerfJSTest', function () { + beforeAll(async function () { + console.info('beforeAll'); + }); + + afterAll(async function () { + console.info('afterAll'); + }); + + const BASE_CONUT = 100; + const htmlText = 'Hello!'; + + /** + * @tc.name clearData_Callback_performance_test_001 + * @tc.desc clearData interface Callback performance test + * @tc.type PERF + * @tc.require I5YP4X + */ + it('clearData_Callback_performance_test_001', 0, async function (done) { + let systemPasteboard = pasteboard.getSystemPasteboard(); + let startTime = new Date().getTime(); + clearDataCallbackPerfTest(0); + + function clearDataCallbackPerfTest(index) { + systemPasteboard.clearData(() => { + if (index < BASE_CONUT) { + clearDataCallbackPerfTest(index + 1); + } else { + computeAverageTime(startTime, BASE_CONUT, 'clearData_Callback_performance_test_001 averageTime:'); + done(); + } + }); + } + }); + + /** + * @tc.name clear_Callback_performance_test_001 + * @tc.desc clear interface Callback performance test + * @tc.type PERF + * @tc.require I5YP4X + */ + it('clear_Callback_performance_test_001', 0, async function (done) { + let systemPasteboard = pasteboard.getSystemPasteboard(); + let startTime = new Date().getTime(); + clearCallbackPerfTest(0); + + function clearCallbackPerfTest(index) { + systemPasteboard.clear(() => { + if (index < BASE_CONUT) { + clearCallbackPerfTest(index + 1); + } else { + computeAverageTime(startTime, BASE_CONUT, 'clear_Callback_performance_test_001 averageTime:'); + done(); + } + }); + } + }); + + /** + * @tc.name setData_Callback_performance_test_001 + * @tc.desc setData interface Callback performance test + * @tc.type PERF + * @tc.require I5YP4X + */ + it('setData_Callback_performance_test_001', 0, async function (done) { + let systemPasteboard = pasteboard.getSystemPasteboard(); + let pasteData = pasteboard.createData(pasteboard.MIMETYPE_TEXT_HTML, htmlText); + let startTime = new Date().getTime(); + setDataCallbackPerfTest(0); + + function setDataCallbackPerfTest(index) { + systemPasteboard.setData(pasteData, () => { + if (index < BASE_CONUT) { + setDataCallbackPerfTest(index + 1); + } else { + computeAverageTime(startTime, BASE_CONUT, 'setData_Callback_performance_test_001 averageTime:'); + done(); + } + }); + } + }); + + /** + * @tc.name setPasteData_Callback_performance_test_001 + * @tc.desc setPasteData interface Callback performance test + * @tc.type PERF + * @tc.require I5YP4X + */ + it('setPasteData_Callback_performance_test_001', 0, async function (done) { + let systemPasteboard = pasteboard.getSystemPasteboard(); + let pasteData = pasteboard.createData(pasteboard.MIMETYPE_TEXT_HTML, htmlText); + let startTime = new Date().getTime(); + setPasteDataCallbackPerfTest(0); + + function setPasteDataCallbackPerfTest(index) { + systemPasteboard.setPasteData(pasteData, () => { + if (index < BASE_CONUT) { + setPasteDataCallbackPerfTest(index + 1); + } else { + computeAverageTime(startTime, BASE_CONUT, 'setPasteData_Callback_performance_test_001 averageTime:'); + done(); + } + }); + } + }); + + /** + * @tc.name hasData_Callback_performance_test_001 + * @tc.desc hasData interface Callback performance test + * @tc.type PERF + * @tc.require I5YP4X + */ + it('hasData_Callback_performance_test_001', 0, async function (done) { + let systemPasteboard = pasteboard.getSystemPasteboard(); + let startTime = new Date().getTime(); + hasDataCallbackPerfTest(0); + + function hasDataCallbackPerfTest(index) { + systemPasteboard.hasData(() => { + if (index < BASE_CONUT) { + hasDataCallbackPerfTest(index + 1); + } else { + computeAverageTime(startTime, BASE_CONUT, 'hasData_Callback_performance_test_001 averageTime:'); + done(); + } + }); + } + }); + + /** + * @tc.name hasPasteData_Callback_performance_test_001 + * @tc.desc hasPasteData interface Callback performance test + * @tc.type PERF + * @tc.require I5YP4X + */ + it('hasPasteData_Callback_performance_test_001', 0, async function (done) { + let systemPasteboard = pasteboard.getSystemPasteboard(); + let startTime = new Date().getTime(); + hasPasteDataCallbackPerfTest(0); + + function hasPasteDataCallbackPerfTest(index) { + systemPasteboard.hasPasteData(() => { + if (index < BASE_CONUT) { + hasPasteDataCallbackPerfTest(index + 1); + } else { + computeAverageTime(startTime, BASE_CONUT, 'hasPasteData_Callback_performance_test_001 averageTime:'); + done(); + } + }); + } + }); + + /** + * @tc.name getData_Callback_performance_test_001 + * @tc.desc getData interface Callback performance test + * @tc.type PERF + * @tc.require I5YP4X + */ + it('getData_Callback_performance_test_001', 0, async function (done) { + let systemPasteboard = pasteboard.getSystemPasteboard(); + let pasteData = pasteboard.createData(pasteboard.MIMETYPE_TEXT_HTML, htmlText); + await systemPasteboard.clearData(); + await systemPasteboard.setData(pasteData); + let startTime = new Date().getTime(); + getDataCallbackPerfTest(0); + + function getDataCallbackPerfTest(index) { + systemPasteboard.getPasteData(() => { + if (index < BASE_CONUT) { + getDataCallbackPerfTest(index + 1); + } else { + computeAverageTime(startTime, BASE_CONUT, 'getData_Callback_performance_test_001 averageTime:'); + done(); + } + }); + } + }); + + /** + * @tc.name getPasteData_Callback_performance_test_001 + * @tc.desc getPasteData interface Callback performance test + * @tc.type PERF + * @tc.require I5YP4X + */ + it('getPasteData_Callback_performance_test_001', 0, async function (done) { + let systemPasteboard = pasteboard.getSystemPasteboard(); + let pasteData = pasteboard.createData(pasteboard.MIMETYPE_TEXT_HTML, htmlText); + await systemPasteboard.clearData(); + await systemPasteboard.setData(pasteData); + let startTime = new Date().getTime(); + getPasteDataCallbackPerfTest(0); + + function getPasteDataCallbackPerfTest(index) { + systemPasteboard.getPasteData(() => { + if (index < BASE_CONUT) { + getPasteDataCallbackPerfTest(index + 1); + } else { + computeAverageTime(startTime, BASE_CONUT, 'getPasteData_Callback_performance_test_001 averageTime:'); + done(); + } + }); + } + }); + + /** + * @tc.name convertToText_Callback_performance_test_001 + * @tc.desc convertToText interface Callback performance test + * @tc.type PERF + * @tc.require I5YP4X + */ + it('convertToText_Callback_performance_test_001', 0, async function (done) { + let pasteDataRecord = pasteboard.createRecord(pasteboard.MIMETYPE_TEXT_HTML, htmlText); + let startTime = new Date().getTime(); + convertToTextCallbackPerfTest(0); + + function convertToTextCallbackPerfTest(index) { + pasteDataRecord.convertToText(() => { + if (index < BASE_CONUT) { + convertToTextCallbackPerfTest(index + 1); + } else { + computeAverageTime(startTime, BASE_CONUT, 'convertToText_Callback_performance_test_001 averageTime:'); + done(); + } + }); + } + }); + + /** + * @tc.name convertToTextV9_Callback_performance_test_001 + * @tc.desc convertToTextV9 interface Callback performance test + * @tc.type PERF + * @tc.require I5YP4X + */ + it('convertToTextV9_Callback_performance_test_001', 0, async function (done) { + let pasteDataRecord = pasteboard.createRecord(pasteboard.MIMETYPE_TEXT_HTML, htmlText); + let startTime = new Date().getTime(); + convertToTextV9CallbackPerfTest(0); + + function convertToTextV9CallbackPerfTest(index) { + pasteDataRecord.convertToTextV9(() => { + if (index < BASE_CONUT) { + convertToTextV9CallbackPerfTest(index + 1); + } else { + computeAverageTime(startTime, BASE_CONUT, 'convertToTextV9_Callback_performance_test_001 averageTime:'); + done(); + } + }); + } + }); + + function computeAverageTime(startTime, baseCount, message) { + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / baseCount; + console.info(message + averageTime); + } +}); diff --git a/pasteboard/interfaces/kits/napi/test/unittest/pasteboardperf/PasteBoardPromiseApiPerfJsunit.test.js b/pasteboard/interfaces/kits/napi/test/unittest/pasteboardperf/PasteBoardPromiseApiPerfJsunit.test.js new file mode 100644 index 00000000..8d37df97 --- /dev/null +++ b/pasteboard/interfaces/kits/napi/test/unittest/pasteboardperf/PasteBoardPromiseApiPerfJsunit.test.js @@ -0,0 +1,277 @@ +/* + * Copyright (C) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the 'License'); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an 'AS IS' BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// @ts-nocheck +import {describe, beforeAll, beforeEach, afterEach, afterAll, it, expect} from 'deccjsunit/index' +import pasteboard from '@ohos.pasteboard' +import image from '@ohos.multimedia.image' + +describe('PasteBoardPerfJSTest', function () { + beforeAll(async function () { + console.info('beforeAll'); + }) + + afterAll(async function () { + console.info('afterAll'); + }) + + const BASE_CONUT = 100; + const htmlText = 'Hello!'; + + + /** + * @tc.name clearData_Promise_performance_test_001 + * @tc.desc clearData interface promise performance test + * @tc.type PERF + * @tc.require I5YP4X + */ + it('clearData_Promise_performance_test_001', 0, async function (done) { + let systemPasteboard = pasteboard.getSystemPasteboard(); + let startTime = new Date().getTime(); + clearDataPromisePerfTest(0); + + function clearDataPromisePerfTest(index) { + systemPasteboard.clearData().then(() => { + if (index < BASE_CONUT) { + clearDataPromisePerfTest(index + 1); + } else { + computeAverageTime(startTime, BASE_CONUT, "clearData_Promise_performance_test_001 averageTime:"); + done(); + } + }); + } + }) + + /** + * @tc.name clear_Promise_performance_test_001 + * @tc.desc clear interface promise performance test + * @tc.type PERF + * @tc.require I5YP4X + */ + it('clear_Promise_performance_test_001', 0, async function (done) { + let systemPasteboard = pasteboard.getSystemPasteboard(); + let startTime = new Date().getTime(); + clearPromisePerfTest(0); + + function clearPromisePerfTest(index) { + systemPasteboard.clearData().then(() => { + if (index < BASE_CONUT) { + clearPromisePerfTest(index + 1); + } else { + computeAverageTime(startTime, BASE_CONUT, "clear_Promise_performance_test_001 averageTime:"); + done(); + } + }); + } + }) + + /** + * @tc.name setData_Promise_performance_test_001 + * @tc.desc setData interface promise performance test + * @tc.type PERF + * @tc.require I5YP4X + */ + it('setData_Promise_performance_test_001', 0, async function (done) { + let systemPasteboard = pasteboard.getSystemPasteboard(); + let pasteData = pasteboard.createData(pasteboard.MIMETYPE_TEXT_HTML, htmlText); + let startTime = new Date().getTime(); + setDataPromisePerfTest(0); + + function setDataPromisePerfTest(index) { + systemPasteboard.setData(pasteData).then(() => { + if (index < BASE_CONUT) { + setDataPromisePerfTest(index + 1); + } else { + computeAverageTime(startTime, BASE_CONUT, "setData_Promise_performance_test_001 averageTime:"); + done(); + } + }); + } + }) + + /** + * @tc.name setPasteData_Promise_performance_test_001 + * @tc.desc setPasteData interface promise performance test + * @tc.type PERF + * @tc.require I5YP4X + */ + it('setPasteData_Promise_performance_test_001', 0, async function (done) { + let systemPasteboard = pasteboard.getSystemPasteboard(); + let pasteData = pasteboard.createData(pasteboard.MIMETYPE_TEXT_HTML, htmlText); + let startTime = new Date().getTime(); + setPasteDataPromisePerfTest(0); + + function setPasteDataPromisePerfTest(index) { + systemPasteboard.setPasteData(pasteData).then(() => { + if (index < BASE_CONUT) { + setPasteDataPromisePerfTest(index + 1); + } else { + computeAverageTime(startTime, BASE_CONUT, "setPasteData_Promise_performance_test_001 averageTime:"); + done(); + } + }); + } + }) + + /** + * @tc.name hasData_Promise_performance_test_001 + * @tc.desc hasData interface promise performance test + * @tc.type PERF + * @tc.require I5YP4X + */ + it('hasData_Promise_performance_test_001', 0, async function (done) { + let systemPasteboard = pasteboard.getSystemPasteboard(); + let startTime = new Date().getTime(); + hasDataPromisePerfTest(0); + + function hasDataPromisePerfTest(index) { + systemPasteboard.hasData().then(() => { + if (index < BASE_CONUT) { + hasDataPromisePerfTest(index + 1); + } else { + computeAverageTime(startTime, BASE_CONUT, "hasData_Promise_performance_test_001 averageTime:"); + done(); + } + }); + } + }) + + /** + * @tc.name hasPasteData_Promise_performance_test_001 + * @tc.desc hasPasteData interface promise performance test + * @tc.type PERF + * @tc.require I5YP4X + */ + it('hasPasteData_Promise_performance_test_001', 0, async function (done) { + let systemPasteboard = pasteboard.getSystemPasteboard(); + let startTime = new Date().getTime(); + hasPasteDataPromisePerfTest(0); + + function hasPasteDataPromisePerfTest(index) { + systemPasteboard.hasPasteData().then(() => { + if (index < BASE_CONUT) { + hasPasteDataPromisePerfTest(index + 1); + } else { + computeAverageTime(startTime, BASE_CONUT, "hasPasteData_Promise_performance_test_001 averageTime:"); + done(); + } + }); + } + }) + + /** + * @tc.name getData_Promise_performance_test_001 + * @tc.desc getData interface promise performance test + * @tc.type PERF + * @tc.require I5YP4X + */ + it('getData_Promise_performance_test_001', 0, async function (done) { + let systemPasteboard = pasteboard.getSystemPasteboard(); + let pasteData = pasteboard.createData(pasteboard.MIMETYPE_TEXT_HTML, htmlText); + await systemPasteboard.clearData(); + await systemPasteboard.setData(pasteData); + let startTime = new Date().getTime(); + getDataPromisePerfTest(0); + + function getDataPromisePerfTest(index) { + systemPasteboard.getData().then(() => { + if (index < BASE_CONUT) { + getDataPromisePerfTest(index + 1); + } else { + computeAverageTime(startTime, BASE_CONUT, "getData_Promise_performance_test_001 averageTime:"); + done(); + } + }); + } + }) + + /** + * @tc.name getPasteData_Promise_performance_test_001 + * @tc.desc getPasteData interface promise performance test + * @tc.type PERF + * @tc.require I5YP4X + */ + it('getPasteData_Promise_performance_test_001', 0, async function (done) { + let systemPasteboard = pasteboard.getSystemPasteboard(); + let pasteData = pasteboard.createData(pasteboard.MIMETYPE_TEXT_HTML, htmlText); + await systemPasteboard.clearData(); + await systemPasteboard.setData(pasteData); + let startTime = new Date().getTime(); + getPasteDataPromisePerfTest(0); + + function getPasteDataPromisePerfTest(index) { + systemPasteboard.getData().then(() => { + if (index < BASE_CONUT) { + getPasteDataPromisePerfTest(index + 1); + } else { + computeAverageTime(startTime, BASE_CONUT, "getPasteData_Promise_performance_test_001 averageTime:"); + done(); + } + }); + } + }) + + /** + * @tc.name convertToText_Promise_performance_test_001 + * @tc.desc convertToText interface promise performance test + * @tc.type PERF + * @tc.require I5YP4X + */ + it('convertToText_Promise_performance_test_001', 0, async function (done) { + let pasteDataRecord = pasteboard.createRecord(pasteboard.MIMETYPE_TEXT_HTML, htmlText); + let startTime = new Date().getTime(); + convertToTextPromisePerfTest(0); + + function convertToTextPromisePerfTest(index) { + pasteDataRecord.convertToText().then(() => { + if (index < BASE_CONUT) { + convertToTextPromisePerfTest(index + 1); + } else { + computeAverageTime(startTime, BASE_CONUT, "convertToText_Promise_performance_test_001 averageTime:"); + done(); + } + }); + } + }) + + /** + * @tc.name convertToTextV9_Promise_performance_test_001 + * @tc.desc convertToTextV9 interface promise performance test + * @tc.type PERF + * @tc.require I5YP4X + */ + it('convertToTextV9_Promise_performance_test_001', 0, async function (done) { + let pasteDataRecord = pasteboard.createRecord(pasteboard.MIMETYPE_TEXT_HTML, htmlText); + let startTime = new Date().getTime(); + convertToTextV9PromisePerfTest(0); + + function convertToTextV9PromisePerfTest(index) { + pasteDataRecord.convertToTextV9().then(() => { + if (index < BASE_CONUT) { + convertToTextV9PromisePerfTest(index + 1); + } else { + computeAverageTime(startTime, BASE_CONUT, "convertToTextV9_Promise_performance_test_001 averageTime:"); + done(); + } + }); + } + }) + + function computeAverageTime(startTime, baseCount, message) { + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / baseCount; + console.info(message + averageTime); + } + +}); diff --git a/pasteboard/interfaces/kits/napi/test/unittest/pasteboardperf/PasteBoardSyncApiPerfJsunit.test.js b/pasteboard/interfaces/kits/napi/test/unittest/pasteboardperf/PasteBoardSyncApiPerfJsunit.test.js new file mode 100644 index 00000000..f0544220 --- /dev/null +++ b/pasteboard/interfaces/kits/napi/test/unittest/pasteboardperf/PasteBoardSyncApiPerfJsunit.test.js @@ -0,0 +1,575 @@ +/* + * Copyright (C) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the 'License'); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an 'AS IS' BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// @ts-nocheck +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from 'deccjsunit/index'; +import pasteboard from '@ohos.pasteboard'; +import image from '@ohos.multimedia.image'; + +describe('PasteBoardPerfJSTest', function () { + beforeAll(async function () { + console.info('beforeAll'); + }); + + afterAll(async function () { + console.info('afterAll'); + }); + + const BASE_CONUT = 200; + const pixelMapBuffer = new ArrayBuffer(10000); + const opt = { + size: { height: 50, width: 50 }, + pixelFormat: 3, + editable: true, + alphaType: 1, + scaleMode: 1, + }; + const htmlText = 'Hello!'; + const uriText = 'https://www.baidu.com/'; + const plainText = 'Hello World!'; + const wantText = { + bundleName: 'com.example.myapplication8', + abilityName: 'com.example.myapplication8.MainAbility', + }; + + /** + * @tc.name getSystemPasteboard_performance_test_001 + * @tc.desc getSystemPasteboard interface performance test + * @tc.type PERF + * @tc.require I5YP4X + */ + it('getSystemPasteboard_performance_test_001', 0, async function (done) { + let startTime = new Date().getTime(); + funcWithNoparam(pasteboard.getSystemPasteboard, BASE_CONUT); + computeAverageTime(startTime, BASE_CONUT, 'getSystemPasteboard_performance_test_001 averageTime:'); + done(); + }); + + /** + * @tc.name createData_performance_test_001 + * @tc.desc createData interface performance test + * @tc.type PERF + * @tc.require I5YP4X + */ + it('createData_performance_test_001', 0, async function (done) { + let pixelMap = await image.createPixelMap(pixelMapBuffer, opt); + let startTime = new Date().getTime(); + funcWithTwoparam(pasteboard.createData, pasteboard.MIMETYPE_PIXELMAP, pixelMap, BASE_CONUT); + computeAverageTime(startTime, BASE_CONUT, 'createData_performance_test_001 averageTime:'); + done(); + }); + + /** + * @tc.name createRecord_performance_test_001 + * @tc.desc createRecord interface performance test + * @tc.type PERF + * @tc.require I5YP4X + */ + it('createRecord_performance_test_001', 0, async function (done) { + let pixelMap = await image.createPixelMap(pixelMapBuffer, opt); + let startTime = new Date().getTime(); + funcWithTwoparam(pasteboard.createRecord, pasteboard.MIMETYPE_PIXELMAP, pixelMap, BASE_CONUT); + computeAverageTime(startTime, BASE_CONUT, 'createRecord_performance_test_001 averageTime:'); + done(); + }); + + /** + * @tc.name createHtmlData_performance_test_001 + * @tc.desc createHtmlData interface performance test + * @tc.type PERF + * @tc.require I5YP4X + */ + it('createHtmlData_performance_test_001', 0, async function (done) { + let startTime = new Date().getTime(); + funcWithOneparam(pasteboard.createHtmlData, htmlText, BASE_CONUT); + computeAverageTime(startTime, BASE_CONUT, 'createHtmlData_performance_test_001 averageTime:'); + done(); + }); + + /** + * @tc.name createWantData_performance_test_001 + * @tc.desc createWantData interface performance test + * @tc.type PERF + * @tc.require I5YP4X + */ + it('createWantData_performance_test_001', 0, async function (done) { + let startTime = new Date().getTime(); + funcWithOneparam(pasteboard.createWantData, wantText, BASE_CONUT); + computeAverageTime(startTime, BASE_CONUT, 'createWantData_performance_test_001 averageTime:'); + done(); + }); + + /** + * @tc.name createPlainTextData_performance_test_001 + * @tc.desc createPlainTextData interface performance test + * @tc.type PERF + * @tc.require I5YP4X + */ + it('createPlainTextData_performance_test_001', 0, async function (done) { + let startTime = new Date().getTime(); + funcWithOneparam(pasteboard.createPlainTextData, plainText, BASE_CONUT); + computeAverageTime(startTime, BASE_CONUT, 'createPlainTextData_performance_test_001 averageTime:'); + done(); + }); + + /** + * @tc.name createUriData_performance_test_001 + * @tc.desc createUriData interface performance test + * @tc.type PERF + * @tc.require I5YP4X + */ + it('createUriData_performance_test_001', 0, async function (done) { + let startTime = new Date().getTime(); + funcWithOneparam(pasteboard.createUriData, uriText, BASE_CONUT); + computeAverageTime(startTime, BASE_CONUT, 'createUriData_performance_test_001 averageTime:'); + done(); + }); + + /** + * @tc.name createHtmlTextRecord_performance_test_001 + * @tc.desc createHtmlTextRecord interface performance test + * @tc.type PERF + * @tc.require I5YP4X + */ + it('createHtmlTextRecord_performance_test_001', 0, async function (done) { + let startTime = new Date().getTime(); + funcWithOneparam(pasteboard.createHtmlTextRecord, htmlText, BASE_CONUT); + computeAverageTime(startTime, BASE_CONUT, 'createHtmlTextRecord_performance_test_001 averageTime:'); + done(); + }); + + /** + * @tc.name createWantRecord_performance_test_001 + * @tc.desc createWantRecord interface performance test + * @tc.type PERF + * @tc.require I5YP4X + */ + it('createWantRecord_performance_test_001', 0, async function (done) { + let startTime = new Date().getTime(); + funcWithOneparam(pasteboard.createWantRecord, wantText, BASE_CONUT); + computeAverageTime(startTime, BASE_CONUT, 'createWantRecord_performance_test_001 averageTime:'); + done(); + }); + + /** + * @tc.name createPlainTextRecord_performance_test_001 + * @tc.desc createPlainTextRecord interface performance test + * @tc.type PERF + * @tc.require I5YP4X + */ + it('createPlainTextRecord_performance_test_001', 0, async function (done) { + let startTime = new Date().getTime(); + funcWithOneparam(pasteboard.createPlainTextRecord, plainText, BASE_CONUT); + computeAverageTime(startTime, BASE_CONUT, 'createPlainTextRecord_performance_test_001 averageTime:'); + done(); + }); + + /** + * @tc.name createUriRecord_performance_test_001 + * @tc.desc createUriRecord interface performance test + * @tc.type PERF + * @tc.require I5YP4X + */ + it('createUriRecord_performance_test_001', 0, async function (done) { + let startTime = new Date().getTime(); + funcWithOneparam(pasteboard.createUriRecord, uriText, BASE_CONUT); + computeAverageTime(startTime, BASE_CONUT, 'createUriRecord_performance_test_001 averageTime:'); + done(); + }); + + /** + * @tc.name addRecord_performance_test_001 + * @tc.desc addRecord interface performance test + * @tc.type PERF + * @tc.require I5YP4X + */ + it('addRecord_performance_test_001', 0, async function (done) { + let pixelMap = await image.createPixelMap(pixelMapBuffer, opt); + let pasteData = pasteboard.createData(pasteboard.MIMETYPE_TEXT_URI, uriText); + let startTime = new Date().getTime(); + funcWithTwoparam(pasteData.addRecord, pasteboard.MIMETYPE_PIXELMAP, pixelMap, BASE_CONUT); + computeAverageTime(startTime, BASE_CONUT, 'addRecord_performance_test_001 averageTime:'); + done(); + }); + + /** + * @tc.name getRecord_performance_test_001 + * @tc.desc getRecord interface performance test + * @tc.type PERF + * @tc.require I5YP4X + */ + it('getRecord_performance_test_001', 0, async function (done) { + let pasteData = pasteboard.createData(pasteboard.MIMETYPE_TEXT_URI, uriText); + let startTime = new Date().getTime(); + funcWithOneparam(pasteData.getRecord, 0, BASE_CONUT); + computeAverageTime(startTime, BASE_CONUT, 'getRecord_performance_test_001 averageTime:'); + done(); + }); + + /** + * @tc.name hasType_performance_test_001 + * @tc.desc hasType interface performance test + * @tc.type PERF + * @tc.require I5YP4X + */ + it('hasType_performance_test_001', 0, async function (done) { + let pasteData = pasteboard.createData(pasteboard.MIMETYPE_TEXT_URI, uriText); + let startTime = new Date().getTime(); + funcWithOneparam(pasteData.hasType, pasteboard.MIMETYPE_PIXELMAP, BASE_CONUT); + computeAverageTime(startTime, BASE_CONUT, 'hasType_performance_test_001 averageTime:'); + done(); + }); + + /** + * @tc.name removeRecord_performance_test_001 + * @tc.desc removeRecord interface performance test + * @tc.type PERF + * @tc.require I5YP4X + */ + it('removeRecord_performance_test_001', 0, async function (done) { + let pasteData = pasteboard.createData(pasteboard.MIMETYPE_TEXT_URI, uriText); + funcWithOneparam(pasteData.addHtmlRecord, htmlText, BASE_CONUT); + let startTime = new Date().getTime(); + funcWithOneparam(pasteData.removeRecord, 0, BASE_CONUT); + computeAverageTime(startTime, BASE_CONUT, 'removeRecord_performance_test_001 averageTime:'); + done(); + }); + + /** + * @tc.name replaceRecord_performance_test_001 + * @tc.desc replaceRecord interface performance test + * @tc.type PERF + * @tc.require I5YP4X + */ + it('replaceRecord_performance_test_001', 0, async function (done) { + let pasteData = pasteboard.createData(pasteboard.MIMETYPE_TEXT_URI, uriText); + let dataRecord = pasteboard.createRecord(pasteboard.MIMETYPE_TEXT_URI, uriText); + let startTime = new Date().getTime(); + funcWithTwoparam(pasteData.replaceRecord, 0, dataRecord, BASE_CONUT); + computeAverageTime(startTime, BASE_CONUT, 'replaceRecord_performance_test_001 averageTime:'); + done(); + }); + + /** + * @tc.name addHtmlRecord_performance_test_001 + * @tc.desc addHtmlRecord interface performance test + * @tc.type PERF + * @tc.require I5YP4X + */ + it('addHtmlRecord_performance_test_001', 0, async function (done) { + let pasteData = pasteboard.createData(pasteboard.MIMETYPE_TEXT_URI, uriText); + let startTime = new Date().getTime(); + funcWithOneparam(pasteData.addHtmlRecord, htmlText, BASE_CONUT); + computeAverageTime(startTime, BASE_CONUT, 'addHtmlRecord_performance_test_001 averageTime:'); + done(); + }); + + /** + * @tc.name addWantRecord_performance_test_001 + * @tc.desc addWantRecord interface performance test + * @tc.type PERF + * @tc.require I5YP4X + */ + it('addWantRecord_performance_test_001', 0, async function (done) { + let pasteData = pasteboard.createData(pasteboard.MIMETYPE_TEXT_URI, uriText); + let startTime = new Date().getTime(); + funcWithOneparam(pasteData.addWantRecord, wantText, BASE_CONUT); + computeAverageTime(startTime, BASE_CONUT, 'addWantRecord_performance_test_001 averageTime:'); + done(); + }); + + /** + * @tc.name addRecord_performance_test_002 + * @tc.desc addRecord interface performance test + * @tc.type PERF + * @tc.require I5YP4X + */ + it('addRecord_performance_test_002', 0, async function (done) { + let pasteData = pasteboard.createData(pasteboard.MIMETYPE_TEXT_URI, uriText); + let dataRecord = pasteboard.createRecord(pasteboard.MIMETYPE_TEXT_URI, uriText); + let startTime = new Date().getTime(); + funcWithOneparam(pasteData.addRecord, dataRecord, BASE_CONUT); + computeAverageTime(startTime, BASE_CONUT, 'addRecord_performance_test_002 averageTime:'); + done(); + }); + + /** + * @tc.name addTextRecord_performance_test_001 + * @tc.desc addTextRecord interface performance test + * @tc.type PERF + * @tc.require I5YP4X + */ + it('addTextRecord_performance_test_001', 0, async function (done) { + let pasteData = pasteboard.createData(pasteboard.MIMETYPE_TEXT_URI, uriText); + let startTime = new Date().getTime(); + funcWithOneparam(pasteData.addTextRecord, plainText, BASE_CONUT); + computeAverageTime(startTime, BASE_CONUT, 'addTextRecord_performance_test_001 averageTime:'); + done(); + }); + + /** + * @tc.name addUriRecord_performance_test_001 + * @tc.desc addUriRecord interface performance test + * @tc.type PERF + * @tc.require I5YP4X + */ + it('addUriRecord_performance_test_001', 0, async function (done) { + let pasteData = pasteboard.createData(pasteboard.MIMETYPE_TEXT_URI, uriText); + let startTime = new Date().getTime(); + funcWithOneparam(pasteData.addUriRecord, uriText, BASE_CONUT); + computeAverageTime(startTime, BASE_CONUT, 'addUriRecord_performance_test_001 averageTime:'); + done(); + }); + + /** + * @tc.name getMimeTypes_performance_test_001 + * @tc.desc getMimeTypes interface performance test + * @tc.type PERF + * @tc.require I5YP4X + */ + it('getMimeTypes_performance_test_001', 0, async function (done) { + let pasteData = pasteboard.createData(pasteboard.MIMETYPE_TEXT_URI, uriText); + let startTime = new Date().getTime(); + funcWithNoparam(pasteData.getMimeTypes, BASE_CONUT); + computeAverageTime(startTime, BASE_CONUT, 'getMimeTypes_performance_test_001 averageTime:'); + done(); + }); + + /** + * @tc.name getPrimaryHtml_performance_test_001 + * @tc.desc getPrimaryHtml interface performance test + * @tc.type PERF + * @tc.require I5YP4X + */ + it('getPrimaryHtml_performance_test_001', 0, async function (done) { + let pasteData = pasteboard.createData(pasteboard.MIMETYPE_TEXT_HTML, htmlText); + let startTime = new Date().getTime(); + funcWithNoparam(pasteData.getPrimaryHtml, BASE_CONUT); + computeAverageTime(startTime, BASE_CONUT, 'getPrimaryHtml_performance_test_001 averageTime:'); + done(); + }); + + /** + * @tc.name getPrimaryWant_performance_test_001 + * @tc.desc getPrimaryWant interface performance test + * @tc.type PERF + * @tc.require I5YP4X + */ + it('getPrimaryWant_performance_test_001', 0, async function (done) { + let pasteData = pasteboard.createData(pasteboard.MIMETYPE_TEXT_WANT, wantText); + let startTime = new Date().getTime(); + funcWithNoparam(pasteData.getPrimaryWant, BASE_CONUT); + computeAverageTime(startTime, BASE_CONUT, 'getPrimaryWant_performance_test_001 averageTime:'); + done(); + }); + + /** + * @tc.name getPrimaryMimeType_performance_test_001 + * @tc.desc getPrimaryMimeType interface performance test + * @tc.type PERF + * @tc.require I5YP4X + */ + it('getPrimaryMimeType_performance_test_001', 0, async function (done) { + let pasteData = pasteboard.createData(pasteboard.MIMETYPE_TEXT_WANT, wantText); + let startTime = new Date().getTime(); + funcWithNoparam(pasteData.getPrimaryMimeType, BASE_CONUT); + computeAverageTime(startTime, BASE_CONUT, 'getPrimaryMimeType_performance_test_001 averageTime:'); + done(); + }); + + /** + * @tc.name getPrimaryUri_performance_test_001 + * @tc.desc getPrimaryUri interface performance test + * @tc.type PERF + * @tc.require I5YP4X + */ + it('getPrimaryUri_performance_test_001', 0, async function (done) { + let pasteData = pasteboard.createData(pasteboard.MIMETYPE_TEXT_URI, uriText); + let startTime = new Date().getTime(); + funcWithNoparam(pasteData.getPrimaryUri, BASE_CONUT); + computeAverageTime(startTime, BASE_CONUT, 'getPrimaryUri_performance_test_001 averageTime:'); + done(); + }); + + /** + * @tc.name getPrimaryPixelMap_performance_test_001 + * @tc.desc getPrimaryPixelMap interface performance test + * @tc.type PERF + * @tc.require I5YP4X + */ + it('getPrimaryPixelMap_performance_test_001', 0, async function (done) { + let pixelMap = await image.createPixelMap(pixelMapBuffer, opt); + let pasteData = pasteboard.createData(pasteboard.MIMETYPE_PIXELMAP, pixelMap); + let startTime = new Date().getTime(); + funcWithNoparam(pasteData.getPrimaryPixelMap, BASE_CONUT); + computeAverageTime(startTime, BASE_CONUT, 'getPrimaryPixelMap_performance_test_001 averageTime:'); + done(); + }); + + /** + * @tc.name getProperty_performance_test_001 + * @tc.desc getProperty interface performance test + * @tc.type PERF + * @tc.require I5YP4X + */ + it('getProperty_performance_test_001', 0, async function (done) { + let pasteData = pasteboard.createData(pasteboard.MIMETYPE_TEXT_URI, uriText); + let startTime = new Date().getTime(); + funcWithNoparam(pasteData.getProperty, BASE_CONUT); + computeAverageTime(startTime, BASE_CONUT, 'getProperty_performance_test_001 averageTime:'); + done(); + }); + + /** + * @tc.name setProperty_performance_test_001 + * @tc.desc setProperty interface performance test + * @tc.type PERF + * @tc.require I5YP4X + */ + it('setProperty_performance_test_001', 0, async function (done) { + let pasteData = pasteboard.createData(pasteboard.MIMETYPE_TEXT_URI, uriText); + let property = pasteData.getProperty(); + let startTime = new Date().getTime(); + funcWithOneparam(pasteData.setProperty, property, BASE_CONUT); + computeAverageTime(startTime, BASE_CONUT, 'setProperty_performance_test_001 averageTime:'); + done(); + }); + + /** + * @tc.name getRecordAt_performance_test_001 + * @tc.desc getRecordAt interface performance test + * @tc.type PERF + * @tc.require I5YP4X + */ + it('getRecordAt_performance_test_001', 0, async function (done) { + let pasteData = pasteboard.createData(pasteboard.MIMETYPE_TEXT_URI, uriText); + let startTime = new Date().getTime(); + funcWithOneparam(pasteData.getRecordAt, 0, BASE_CONUT); + computeAverageTime(startTime, BASE_CONUT, 'getRecordAt_performance_test_001 averageTime:'); + done(); + }); + + /** + * @tc.name getRecordCount_performance_test_001 + * @tc.desc getRecordCount interface performance test + * @tc.type PERF + * @tc.require I5YP4X + */ + it('getRecordCount_performance_test_001', 0, async function (done) { + let pasteData = pasteboard.createData(pasteboard.MIMETYPE_TEXT_URI, uriText); + let startTime = new Date().getTime(); + funcWithNoparam(pasteData.getRecordCount, BASE_CONUT); + computeAverageTime(startTime, BASE_CONUT, 'getRecordCount_performance_test_001 averageTime:'); + done(); + }); + + /** + * @tc.name hasMimeType_performance_test_001 + * @tc.desc hasMimeType interface performance test + * @tc.type PERF + * @tc.require I5YP4X + */ + it('hasMimeType_performance_test_001', 0, async function (done) { + let pasteData = pasteboard.createData(pasteboard.MIMETYPE_TEXT_URI, uriText); + let startTime = new Date().getTime(); + funcWithOneparam(pasteData.hasMimeType, pasteboard.MIMETYPE_TEXT_URI, BASE_CONUT); + computeAverageTime(startTime, BASE_CONUT, 'hasMimeType_performance_test_001 averageTime:'); + done(); + }); + + /** + * @tc.name removeRecordAt_performance_test_001 + * @tc.desc removeRecordAt interface performance test + * @tc.type PERF + * @tc.require I5YP4X + */ + it('removeRecordAt_performance_test_001', 0, async function (done) { + let pasteData = pasteboard.createData(pasteboard.MIMETYPE_TEXT_URI, uriText); + let startTime = new Date().getTime(); + funcWithOneparam(pasteData.removeRecordAt, 0, BASE_CONUT); + computeAverageTime(startTime, BASE_CONUT, 'removeRecordAt_performance_test_001 averageTime:'); + done(); + }); + + /** + * @tc.name replaceRecordAt_performance_test_001 + * @tc.desc replaceRecordAt interface performance test + * @tc.type PERF + * @tc.require I5YP4X + */ + it('replaceRecordAt_performance_test_001', 0, async function (done) { + let pasteData = pasteboard.createData(pasteboard.MIMETYPE_TEXT_URI, uriText); + let dataRecord = pasteboard.createRecord(pasteboard.MIMETYPE_TEXT_HTML, htmlText); + let startTime = new Date().getTime(); + funcWithTwoparam(pasteData.replaceRecordAt, 0, dataRecord, BASE_CONUT); + computeAverageTime(startTime, BASE_CONUT, 'replaceRecordAt_performance_test_001 averageTime:'); + done(); + }); + + /** + * @tc.name on_performance_test_001 + * @tc.desc on interface performance test + * @tc.type PERF + * @tc.require I5YP4X + */ + it('on_performance_test_001', 0, async function (done) { + let systemPasteboard = pasteboard.getSystemPasteboard(); + let startTime = new Date().getTime(); + funcWithTwoparam(systemPasteboard.on, 'update', contentChanges, BASE_CONUT); + computeAverageTime(startTime, BASE_CONUT, 'on_performance_test_001 averageTime:'); + done(); + }); + + /** + * @tc.name off_performance_test_001 + * @tc.desc off interface performance test + * @tc.type PERF + * @tc.require I5YP4X + */ + it('off_performance_test_001', 0, async function (done) { + let systemPasteboard = pasteboard.getSystemPasteboard(); + let startTime = new Date().getTime(); + funcWithTwoparam(systemPasteboard.off, 'update', contentChanges, BASE_CONUT); + computeAverageTime(startTime, BASE_CONUT, 'off_performance_test_001 averageTime:'); + done(); + }); + + function funcWithNoparam(func, count) { + for (let index = 0; index < count; index++) { + func(); + } + } + + function funcWithOneparam(func, param, count) { + for (let index = 0; index < count; index++) { + func(param); + } + } + + function funcWithTwoparam(func, paramOne, paramTwo, count) { + for (let index = 0; index < count; index++) { + func(paramOne, paramTwo); + } + } + + function computeAverageTime(startTime, baseCount, message) { + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / baseCount; + console.info(message + averageTime); + } + + function contentChanges() { + console.info('#EVENT: The content is changed in the pasteboard'); + } +}); diff --git a/pasteboard/pasteboard.gni b/pasteboard/pasteboard.gni new file mode 100644 index 00000000..78bb4309 --- /dev/null +++ b/pasteboard/pasteboard.gni @@ -0,0 +1,48 @@ +# Copyright (C) 2021-2023 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ability_runtime_napi_path = + "//foundation/ability/ability_runtime/frameworks/js/napi" + +pasteboard_root_path = "//foundation/distributeddatamgr/pasteboard" + +pasteboard_kits_path = "${pasteboard_root_path}/kits" + +pasteboard_innerkits_path = "${pasteboard_root_path}/framework/innerkits" + +pasteboard_framework_path = "${pasteboard_root_path}/framework/framework" + +pasteboard_utils_path = "${pasteboard_root_path}/utils" + +pasteboard_service_path = "${pasteboard_root_path}/services" + +filemanagement_service_path = "//foundation/filemanagement/dfs_service/services" + +declare_args() { + pb_dlp_part_enabled = true + pb_device_info_manager_part_enabled = true + pb_device_manager_part_enabled = true + + if (defined(global_parts_info) && + !defined(global_parts_info.security_dlp_permission_service)) { + pb_dlp_part_enabled = false + } + if (defined(global_parts_info) && + !defined(global_parts_info.deviceprofile_device_info_manager)) { + pb_device_info_manager_part_enabled = false + } + if (defined(global_parts_info) && + !defined(global_parts_info.distributedhardware_device_manager)) { + pb_device_manager_part_enabled = false + } +} diff --git a/pasteboard/pasteboardEvent.yaml b/pasteboard/pasteboardEvent.yaml new file mode 100644 index 00000000..39de7495 --- /dev/null +++ b/pasteboard/pasteboardEvent.yaml @@ -0,0 +1,79 @@ + +# Copyright (c) 2022-2023 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +##################################################### +# below is the format of defining event # +##################################################### +#domain: domain name. [Only one domain name can be defined at the top] +# +#author: the author name who defined this event. +#date: the date when this event was defined, format is YYYY-MM-DD. +#logged: source file which refer to this event. +#usage: the usage of this event. +#//Define event name and event properties. +#@EVENT_NAME: the event definition part begin. +# // __BASE is used for defining the basic info of the event. +# // "type" optional values are: FAULT, STATISTICS, SECURITY, BEHAVIOR. +# // "level" optional values are: CRITICAL, MINOR. +# // "tag" set tags with may used by subscriber of this event, multiple tags devided by space. +# // "desc" full description of this event. +# @PARAMETER: {type: parameter type, arrsize: array length(optional), desc: parameter description}. +# // follow the __BASE block, each line defines a parameter of this event. +# // "type" optional values are: INT8, UINT8, INT16, UINT16, INT32, UINT32, INT64, UINT64, FLOAT, DOUBLE, STRING. +# // "arrsize" of the parameter is an array, set a non-zero value. +# // "desc" full description of this parameter. + +##################################################### +# Example of some hiviewdfx events definition # +##################################################### + +domain: PASTEBOARD + +PASTEBOARD_FAULT: + __BASE: {type: FAULT, level: CRITICAL, desc: The event is database fault } + USER_ID: {type: INT32, desc: app id } + FAULT_CODE: {type: STRING, desc: fault code } + +TIME_CONSUMING_STATISTIC: + __BASE: {type: STATISTIC, level: MINOR, desc: The event is api visit statistic } + PASTEBOARD_STATE: {type: STRING, desc: Pasteboard state } + NET_TYPE: {type: STRING, desc: net type } + DATA_LEVLE: {type: STRING, desc: Data level } + CONSUMING_DATA: {type: STRING, desc: Consuming data } + +PASTEBOARD_BEHAVIOUR: + __BASE: {type: BEHAVIOR, level: MINOR, desc: The event is behaviour record } + PASTEBOARD_STATE: {type: STRING, desc: The counts of time consuming level one} + TOP_ONE_APP: {type: STRING, desc: The counts of top one calling pasteboard } + TOP_TOW_APP: {type: STRING, desc: The counts of top two calling pasteboard } + TOP_THREE_APP: {type: STRING, desc: The counts of top three calling pasteboard } + TOP_FOUR_APP: {type: STRING, desc: The counts of top four calling pasteboard } + TOP_FIVE_APP: {type: STRING, desc: The counts of top five calling pasteboard } + TOP_SIX_APP: {type: STRING, desc: The counts of top six calling pasteboard} + TOP_SEVEN_APP: {type: STRING, desc: The counts of top seven calling pasteboard } + TOP_EIGHT_APP: {type: STRING, desc: The counts of top eight calling pasteboard } + TOP_NINE_APP: {type: STRING, desc: The counts of top nine calling pasteboard } + TOP_TEN_APP: {type: STRING, desc: The counts of top ten calling pasteboard } + +USE_BEHAVIOUR: + __BASE: {type: BEHAVIOR, level: MINOR, desc: The event is behaviour record of access } + PASTEBOARD_STATE: {type: STRING, desc: Pasteboard state } + BOOTTIME: {type: STRING, desc: Boot time } + WALLTIME: {type: STRING, desc: Access pasteboard time} + RESULT: {type: INT32, desc: The result of access pasteboard } + OPERATE_APP: {type: STRING, desc: The app to access pasteboard } + PRI_MIME_TYPE: {type: STRING, desc: Primary mime type } + ISLOCALPASTE: {type: INT32, desc: IsLocalPaste} + ISREMOTE: {type: INT32, desc: IsRemote } + SHAREOPTION: {type: STRING, desc: ShareOption } \ No newline at end of file diff --git a/pasteboard/profile/3701.json b/pasteboard/profile/3701.json new file mode 100644 index 00000000..56723c31 --- /dev/null +++ b/pasteboard/profile/3701.json @@ -0,0 +1,20 @@ +{ + "process": "pasteboard_service", + "systemability": [ + { + "name": 3701, + "libpath": "libpasteboard_service.z.so", + "run-on-create": false, + "distributed": true, + "dump_level": 1, + "start-on-demand": { + "deviceonline": [ + { + "name": "deviceonline", + "value": "on" + } + ] + } + } + ] +} diff --git a/pasteboard/profile/BUILD.gn b/pasteboard/profile/BUILD.gn new file mode 100644 index 00000000..a3f2121c --- /dev/null +++ b/pasteboard/profile/BUILD.gn @@ -0,0 +1,19 @@ +# Copyright (c) 2023 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos/sa_profile/sa_profile.gni") + +ohos_sa_profile("distributeddatamgr_pasteboard_sa_profiles") { + sources = [ "3701.json" ] + part_name = "pasteboard" +} diff --git a/pasteboard/services/BUILD.gn b/pasteboard/services/BUILD.gn new file mode 100644 index 00000000..d8366d4c --- /dev/null +++ b/pasteboard/services/BUILD.gn @@ -0,0 +1,150 @@ +# Copyright (C) 2023 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") +import("//foundation/distributeddatamgr/pasteboard/pasteboard.gni") +import("//foundation/window/window_manager/windowmanager_aafwk.gni") + +config("pasteboard_service_config") { + visibility = [ ":*" ] + visibility += [ "//foundation/distributeddatamgr/pasteboard/test/fuzztest/pasteboardservice_fuzzer/*" ] + include_dirs = [ + "dfx/src", + "dfx/src/behaviour", + "dfx/src/statistic", + "dfx/src/fault", + "zidl/include", + "account/include", + "core/include", + "load/include", + "${filemanagement_service_path}/distributedfiledaemon/include/ipc", + "${pasteboard_innerkits_path}/include", + "${pasteboard_utils_path}/mock/include", + "${pasteboard_utils_path}/native/include", + "${pasteboard_utils_path}/system/safwk/native/include", + "${pasteboard_framework_path}/framework/include", + "${pasteboard_framework_path}/framework/include/device", + "//commonlibrary/c_utils/base/include", + ] + ldflags = [ "-Wl,--exclude-libs=ALL" ] + cflags = [ + "-fdata-sections", + "-ffunction-sections", + "-fvisibility=hidden", + ] +} + +ohos_shared_library("pasteboard_service") { + branch_protector_ret = "pac_ret" + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + } + sources = [ + "${pasteboard_innerkits_path}/src/paste_data.cpp", + "${pasteboard_innerkits_path}/src/paste_data_record.cpp", + "account/src/account_manager.cpp", + "core/src/pasteboard_dialog.cpp", + "core/src/pasteboard_service.cpp", + "dfx/src/behaviour/pasteboard_behaviour_reporter_impl.cpp", + "dfx/src/calculate_time_consuming.cpp", + "dfx/src/command.cpp", + "dfx/src/fault/pasteboard_fault_impl.cpp", + "dfx/src/hiview_adapter.cpp", + "dfx/src/pasteboard_dump_helper.cpp", + "dfx/src/pasteboard_trace.cpp", + "dfx/src/reporter.cpp", + "dfx/src/statistic/time_consuming_statistic_impl.cpp", + "load/src/config.cpp", + "load/src/loader.cpp", + "zidl/src/pasteboard_observer_proxy.cpp", + "zidl/src/pasteboard_service_stub.cpp", + ] + public_configs = [ + "//commonlibrary/c_utils/base:utils_config", + ":pasteboard_service_config", + ] + + cflags_cc = [ + "-fstack-protector", + "-D_FORTIFY_SOURCE=2", + "-O2", + ] + + deps = [ + "${pasteboard_framework_path}:pasteboard_framework", + "//foundation/distributeddatamgr/pasteboard/framework/framework:pasteboard_framework", + "//foundation/distributeddatamgr/pasteboard/framework/tlv:pasteboard_tlv", + "//foundation/distributeddatamgr/pasteboard/framework/uri:pasteboard_uri", + ] + defines = [] + + configs = [ "//third_party/cJSON:cJSON_config" ] + + deps += [ "//third_party/cJSON:cjson" ] + + external_deps = [ + "ability_base:base", + "ability_base:want", + "ability_base:zuri", + "ability_runtime:ability_manager", + "ability_runtime:uri_permission_mgr", + "ability_runtime:wantagent_innerkits", + "access_token:libaccesstoken_sdk", + "app_file_service:remote_file_share_native", + "bundle_framework:appexecfwk_base", + "bundle_framework:appexecfwk_core", + "c_utils:utils", + "common_event_service:cesfwk_innerkits", + "dfs_service:distributed_file_daemon_kit_inner", + "eventhandler:libeventhandler", + "hilog:libhilog", + "hisysevent:libhisysevent", + "hitrace:hitrace_meter", + "hitrace:libhitracechain", + "image_framework:image_native", + "imf:inputmethod_client", + "init:libbeget_proxy", + "init:libbegetutil", + "input:libmmi-client", + "ipc:ipc_core", + "os_account:os_account_innerkits", + "safwk:system_ability_fwk", + "samgr:samgr_proxy", + "time_service:time_client", + "window_manager:libwm", + ] + if (scene_board_enabled) { + external_deps += [ "window_manager:libwm_lite" ] + defines += [ "SCENE_BOARD_ENABLE" ] + } else { + external_deps += [ "window_manager:libwm" ] + } + if (pb_dlp_part_enabled) { + external_deps += [ "dlp_permission_service:libdlp_permission_sdk" ] + defines += [ "WITH_DLP" ] + } + + if (pb_device_info_manager_part_enabled) { + external_deps += [ "device_info_manager:distributed_device_profile_client" ] + defines += [ "PB_DEVICE_INFO_MANAGER_ENABLE" ] + } + + if (pb_device_manager_part_enabled) { + external_deps += [ "device_manager:devicemanagersdk" ] + defines += [ "PB_DEVICE_MANAGER_ENABLE" ] + } + subsystem_name = "distributeddatamgr" + part_name = "pasteboard" +} diff --git a/pasteboard/services/account/include/account_manager.h b/pasteboard/services/account/include/account_manager.h new file mode 100644 index 00000000..32262237 --- /dev/null +++ b/pasteboard/services/account/include/account_manager.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_PASTEBOARD_SERVICES_ACCOUNT_ACCOUNT_MANAGER_H +#define OHOS_PASTEBOARD_SERVICES_ACCOUNT_ACCOUNT_MANAGER_H +#include +namespace OHOS::MiscServices { +class AccountManager { +public: + static AccountManager &GetInstance(); + std::string GetCurrentAccount(); + +private: + AccountManager() = default; + ~AccountManager() = default; +}; +} // namespace OHOS::MiscServices +#endif // OHOS_PASTEBOARD_SERVICES_ACCOUNT_ACCOUNT_MANAGER_H diff --git a/pasteboard/services/account/src/account_manager.cpp b/pasteboard/services/account/src/account_manager.cpp new file mode 100644 index 00000000..dd1aec43 --- /dev/null +++ b/pasteboard/services/account/src/account_manager.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "account_manager.h" +namespace OHOS::MiscServices { +AccountManager &AccountManager::GetInstance() +{ + static AccountManager instance; + return instance; +} + +std::string AccountManager::GetCurrentAccount() +{ + return ""; +} +} // namespace OHOS::MiscServices diff --git a/pasteboard/services/core/include/i_pasteboard_observer.h b/pasteboard/services/core/include/i_pasteboard_observer.h new file mode 100644 index 00000000..c8c96ec4 --- /dev/null +++ b/pasteboard/services/core/include/i_pasteboard_observer.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PASTE_BOARD_CHANGER_OBSERVER_INTERFACE_H +#define PASTE_BOARD_CHANGER_OBSERVER_INTERFACE_H + +#include "iremote_broker.h" + +namespace OHOS { +namespace MiscServices { +enum class PasteboardEventStatus { + PASTEBOARD_CLEAR = 1, + PASTEBOARD_READ = 2, + PASTEBOARD_WRITE = 3 +}; +class IPasteboardChangedObserver : public IRemoteBroker { +public: + virtual void OnPasteboardChanged() = 0; + virtual void OnPasteboardEvent(std::string bundleName, int32_t status) = 0; + virtual ~IPasteboardChangedObserver() = default; + DECLARE_INTERFACE_DESCRIPTOR(u"ohos.miscservices.pasteboard.IPasteboardChangedObserver"); +}; +} // namespace MiscServices +} // namespace OHOS +#endif // PASTE_BOARD_CHANGER_OBSERVER_INTERFACE_H diff --git a/pasteboard/services/core/include/i_pasteboard_service.h b/pasteboard/services/core/include/i_pasteboard_service.h new file mode 100644 index 00000000..1ed73b2a --- /dev/null +++ b/pasteboard/services/core/include/i_pasteboard_service.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PASTE_BOARD_SERVICE_INTERFACE_H +#define PASTE_BOARD_SERVICE_INTERFACE_H + +#include "i_pasteboard_observer.h" +#include "iremote_broker.h" +#include "paste_data.h" + +namespace OHOS { +namespace MiscServices { +class IPasteboardService : public IRemoteBroker { +public: + virtual void Clear() = 0; + virtual int32_t GetPasteData(PasteData &data) = 0; + virtual bool HasPasteData() = 0; + virtual int32_t SetPasteData(PasteData &pasteData) = 0; + virtual bool IsRemoteData() = 0; + virtual int32_t GetDataSource(std::string &bundleName) = 0; + virtual bool HasDataType(const std::string &mimeType) = 0; + virtual void AddPasteboardChangedObserver(const sptr &observer) = 0; + virtual void RemovePasteboardChangedObserver(const sptr &observer) = 0; + virtual void RemoveAllChangedObserver() = 0; + virtual void AddPasteboardEventObserver(const sptr &observer) = 0; + virtual void RemovePasteboardEventObserver(const sptr &observer) = 0; + virtual void RemoveAllEventObserver() = 0; + DECLARE_INTERFACE_DESCRIPTOR(u"ohos.miscservices.pasteboard.IPasteboardService"); +}; +} // namespace MiscServices +} // namespace OHOS +#endif // PASTE_BOARD_SERVICE_INTERFACE_H \ No newline at end of file diff --git a/pasteboard/services/core/include/pasteboard_common_event_subscriber.h b/pasteboard/services/core/include/pasteboard_common_event_subscriber.h new file mode 100644 index 00000000..7e560ab5 --- /dev/null +++ b/pasteboard/services/core/include/pasteboard_common_event_subscriber.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PASTEBOARD_COMMON_EVENT_SUBSCRIBER_H +#define PASTEBOARD_COMMON_EVENT_SUBSCRIBER_H + +#include "common_event_subscriber.h" +#include "common_event_support.h" + +namespace OHOS::MiscServices { +class PasteBoardCommonEventSubscriber : public EventFwk::CommonEventSubscriber { +public: + PasteBoardCommonEventSubscriber(const EventFwk::CommonEventSubscribeInfo &subscribeInfo) + : EventFwk::CommonEventSubscriber(subscribeInfo) + {} + ~PasteBoardCommonEventSubscriber() = default; + void OnReceiveEvent(const EventFwk::CommonEventData &data) override; +private: + std::mutex mutex_; +}; +} // namespace OHOS::MiscServices +#endif // PASTEBOARD_COMMON_EVENT_SUBSCRIBER_H diff --git a/pasteboard/services/core/include/pasteboard_dialog.h b/pasteboard/services/core/include/pasteboard_dialog.h new file mode 100644 index 00000000..589d162d --- /dev/null +++ b/pasteboard/services/core/include/pasteboard_dialog.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PASTEBOARD_INTERFACES_KITS_NAPI_SRC_PASTE_BOARD_DAILOG_H +#define PASTEBOARD_INTERFACES_KITS_NAPI_SRC_PASTE_BOARD_DAILOG_H +#include +#include +#include + +#include "ability_manager_interface.h" +#include "refbase.h" + +namespace OHOS::MiscServices { +class DialogConnection; +class PasteBoardDialog { +public: + struct ToastMessageInfo { + std::string fromAppName{ "unknown" }; + std::string toAppName{ "unknown" }; + }; + static constexpr uint32_t POPUP_INTERVAL = 1; // seconds + static constexpr uint32_t MAX_LIFE_TIME = 300; // seconds + static constexpr uint32_t SHOW_TOAST_TIME = 2000; // milliseconds + static constexpr const char *DEFAULT_LABEL = "unknown"; + using Cancel = std::function; + static PasteBoardDialog &GetInstance(); + int32_t ShowToast(const ToastMessageInfo &message); + void CancelToast(); + +private: + static sptr GetAbilityManagerService(); + + static constexpr const char *PASTEBOARD_DIALOG_APP = "com.ohos.pasteboarddialog"; + static constexpr const char *PASTEBOARD_TOAST_ABILITY = "ToastExtensionAbility"; + + std::mutex connectionLock_; + sptr connection_; +}; +} // namespace OHOS::MiscServices +#endif // PASTEBOARD_INTERFACES_KITS_NAPI_SRC_PASTE_BOARD_DAILOG_H diff --git a/pasteboard/services/core/include/pasteboard_serv_ipc_interface_code.h b/pasteboard/services/core/include/pasteboard_serv_ipc_interface_code.h new file mode 100644 index 00000000..1c4b87d4 --- /dev/null +++ b/pasteboard/services/core/include/pasteboard_serv_ipc_interface_code.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PASTE_BOARD_PASTEBOARD_SERV_IPC_INTERFACE_CODE_H +#define PASTE_BOARD_PASTEBOARD_SERV_IPC_INTERFACE_CODE_H + +/* SAID: 3701 */ +namespace OHOS { +namespace Security { +namespace PasteboardServ { +enum PasteboardServiceInterfaceCode { + GET_PASTE_DATA = 0, + HAS_PASTE_DATA = 1, + SET_PASTE_DATA = 2, + CLEAR_ALL = 3, + ADD_CHANGED_OBSERVER = 4, + DELETE_CHANGED_OBSERVER = 5, + DELETE_ALL_CHANGED_OBSERVER = 6, + ADD_EVENT_OBSERVER = 7, + DELETE_EVENT_OBSERVER = 8, + DELETE_ALL_EVENT_OBSERVER = 9, + IS_REMOTE_DATA = 10, + GET_DATA_SOURCE = 11, + HAS_DATA_TYPE = 12, +}; + +enum PasteboardObserverInterfaceCode { + ON_PASTE_BOARD_CHANGE = 0, + ON_PASTE_BOARD_EVENT = 1, +}; +} // namespace PasteboardServ +} // namespace Security +} // namespace OHOS +#endif // PASTE_BOARD_PASTEBOARD_SERV_IPC_INTERFACE_CODE_H diff --git a/pasteboard/services/core/include/pasteboard_service.h b/pasteboard/services/core/include/pasteboard_service.h new file mode 100644 index 00000000..a37e762a --- /dev/null +++ b/pasteboard/services/core/include/pasteboard_service.h @@ -0,0 +1,205 @@ +/* + * Copyright (C) 2021-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PASTE_BOARD_SERVICE_H +#define PASTE_BOARD_SERVICE_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "bundle_mgr_interface.h" +#include "bundle_mgr_proxy.h" +#include "clip/clip_plugin.h" +#include "event_handler.h" +#include "i_pasteboard_observer.h" +#include "iremote_object.h" +#include "pasteboard_common_event_subscriber.h" +#include "paste_data.h" +#include "pasteboard_dump_helper.h" +#include "pasteboard_service_stub.h" +#include "system_ability.h" + +namespace OHOS { +namespace MiscServices { +const std::int32_t ERROR_USERID = -1; +const std::int32_t RESULT_OK = 0; +enum class ServiceRunningState { STATE_NOT_START, STATE_RUNNING }; +struct AppInfo { + std::string bundleName = "com.pasteboard.default"; + int32_t tokenType = -1; + int32_t userId = ERROR_USERID; + uint32_t tokenId; +}; + +struct HistoryInfo { + std::string time; + std::string bundleName; + std::string state; + std::string remote; +}; + +class PasteboardService final : public SystemAbility, public PasteboardServiceStub { + DECLARE_SYSTEM_ABILITY(PasteboardService) + +public: + API_EXPORT PasteboardService(); + API_EXPORT ~PasteboardService(); + virtual void Clear() override; + virtual int32_t GetPasteData(PasteData &data) override; + virtual bool HasPasteData() override; + virtual int32_t SetPasteData(PasteData &pasteData) override; + virtual bool IsRemoteData() override; + virtual bool HasDataType(const std::string &mimeType) override; + virtual int32_t GetDataSource(std::string &bundleNme) override; + virtual void AddPasteboardChangedObserver(const sptr &observer) override; + virtual void RemovePasteboardChangedObserver(const sptr &observer) override; + virtual void RemoveAllChangedObserver() override; + virtual void AddPasteboardEventObserver(const sptr &observer) override; + virtual void RemovePasteboardEventObserver(const sptr &observer) override; + virtual void RemoveAllEventObserver() override; + virtual void OnStart() override; + virtual void OnStop() override; + static int32_t currentUserId; + size_t GetDataSize(PasteData &data) const; + bool SetPasteboardHistory(HistoryInfo &info); + int Dump(int fd, const std::vector &args) override; + +private: + using Event = ClipPlugin::GlobalEvent; + using ServiceListenerFunc = void (PasteboardService::*)(); + static constexpr const int32_t LISTENING_SERVICE[] = { DISTRIBUTED_HARDWARE_DEVICEMANAGER_SA_ID, + DISTRIBUTED_DEVICE_PROFILE_SA_ID, WINDOW_MANAGER_SERVICE_ID }; + static constexpr const char *PLUGIN_NAME = "distributed_clip"; + static constexpr uint32_t PLAIN_INDEX = 0; + static constexpr uint32_t HTML_INDEX = 1; + static constexpr uint32_t URI_INDEX = 2; + static constexpr uint32_t WANT_INDEX = 3; + static constexpr uint32_t PIXELMAP_INDEX = 4; + static constexpr uint32_t MAX_INDEX_LENGTH = 8; + static constexpr const pid_t EDM_UID = 3057; + static constexpr const pid_t ROOT_UID = 0; + static constexpr uint32_t EXPIRATION_INTERVAL = 2; + static constexpr int MIN_TRANMISSION_TIME = 600; + static constexpr uint64_t ONE_HOUR_MILLISECONDS = 60 * 60 * 1000; + struct classcomp { + bool operator()(const sptr &l, const sptr &r) const + { + return l->AsObject() < r->AsObject(); + } + }; + using ObserverMap = std::map, classcomp>>>; + void AddSysAbilityListener(); + int32_t Init(); + static int32_t GetCurrentAccountId(); + std::string DumpHistory() const; + std::string DumpData(); + void NotifyObservers(std::string bundleName, PasteboardEventStatus status); + void InitServiceHandler(); + bool IsCopyable(uint32_t tokenId) const; + + virtual int32_t SavePasteData(std::shared_ptr &pasteData) override; + void SetPasteDataDot(PasteData &pasteData); + void GetPasteDataDot(PasteData &pasteData, const std::string &bundleName); + bool GetPasteData(AppInfo &appInfo, PasteData &data, bool isFocusedApp); + bool CheckPasteData(AppInfo &appInfo, PasteData &data, bool isFocusedApp); + bool GetRemoteData(AppInfo &appInfo, PasteData &data, bool isFocusedApp); + void CheckUriPermission(PasteData &data, std::vector &grantUris, const std::string &targetBundleName); + void GrantUriPermission(PasteData &data, const std::string &targetBundleName); + void RevokeUriPermission(PasteData &lastData); + void GenerateDistributedUri(PasteData &data); + bool IsPermissionGranted(const std::string& perm, uint32_t tokenId); + bool isBundleOwnUriPermission(const std::string &bundleName, Uri &uri); + void CheckAppUriPermission(PasteData &data); + std::string GetAppLabel(uint32_t tokenId); + sptr GetAppBundleManager(); + void EstablishP2PLink(); + uint8_t GenerateDataType(PasteData &data); + bool HasDistributedDataType(const std::string &mimeType); + + std::shared_ptr GetDistributedData(int32_t user); + bool SetDistributedData(int32_t user, PasteData &data); + bool HasDistributedData(int32_t user); + bool GetDistributedEvent(std::shared_ptr plugin, int32_t user, Event &event); + bool CleanDistributedData(int32_t user); + void OnConfigChange(bool isOn); + std::shared_ptr GetClipPlugin(); + + static std::string GetTime(); + bool IsDataAged(); + bool HasPastePermission(uint32_t tokenId, bool isFocusedApp, const std::shared_ptr &pasteData); + static AppInfo GetAppInfo(uint32_t tokenId); + static std::string GetAppBundleName(const AppInfo &appInfo); + static bool IsDefaultIME(const AppInfo &appInfo); + static bool IsFocusedApp(uint32_t tokenId); + static void SetLocalPasteFlag(bool isCrossPaste, uint32_t tokenId, PasteData &pasteData); + void ShowHintToast(bool isValid, uint32_t tokenId, const std::shared_ptr &pasteData); + void SetWebViewPasteData(PasteData &pasteData, const std::string &bundleName); + void OnAddSystemAbility(int32_t systemAbilityId, const std::string &deviceId) override; + void DevManagerInit(); + void DevProfileInit(); + ServiceRunningState state_; + std::shared_ptr serviceHandler_; + std::recursive_mutex clipMutex_; + std::mutex hintMutex_; + std::mutex observerMutex_; + ObserverMap observerChangedMap_; + ObserverMap observerEventMap_; + ClipPlugin::GlobalEvent currentEvent_; + ClipPlugin::GlobalEvent remoteEvent_; + const std::string filePath_ = ""; + std::map> clips_; + std::map> hints_; + std::map copyTime_; + std::set readBundles_; + std::shared_ptr commonEventSubscriber_ = nullptr; + + std::recursive_mutex mutex; + std::shared_ptr clipPlugin_ = nullptr; + std::atomic sequenceId_ = 0; + static std::mutex historyMutex_; + static std::vector dataHistory_; + static std::shared_ptr copyHistory; + static std::shared_ptr copyData; + std::atomic setting_ = false; + std::mutex remoteMutex_; + std::map ServiceListenerFunc_; + std::map typeMap_ = { + { MIMETYPE_TEXT_PLAIN, PLAIN_INDEX }, + { MIMETYPE_TEXT_HTML, HTML_INDEX }, + { MIMETYPE_TEXT_URI, URI_INDEX }, + { MIMETYPE_TEXT_WANT, WANT_INDEX }, + { MIMETYPE_PIXELMAP, PIXELMAP_INDEX } + }; + + std::map p2pMap_ = {}; + + void AddObserver(const sptr &observer, ObserverMap &observerMap); + void RemoveSingleObserver(const sptr &observer, ObserverMap &observerMap); + void RemoveAllObserver(ObserverMap &observerMap); + inline bool IsCallerUidValid(); + bool HasLocalDataType(const std::string &mimeType); +}; +} // namespace MiscServices +} // namespace OHOS +#endif // PASTE_BOARD_SERVICE_H diff --git a/pasteboard/services/core/src/pasteboard_dialog.cpp b/pasteboard/services/core/src/pasteboard_dialog.cpp new file mode 100644 index 00000000..a7943bc3 --- /dev/null +++ b/pasteboard/services/core/src/pasteboard_dialog.cpp @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "pasteboard_dialog.h" + +#include "ability_connect_callback_stub.h" +#include "in_process_call_wrapper.h" +#include "iservice_registry.h" +#include "pasteboard_hilog.h" +#include "system_ability_definition.h" + +namespace OHOS::MiscServices { +using namespace OHOS::AAFwk; +class DialogConnection : public AAFwk::AbilityConnectionStub { +public: + explicit DialogConnection(PasteBoardDialog::Cancel cancel) : cancel_(std::move(cancel)) + { + } + DialogConnection(const DialogConnection &) = delete; + DialogConnection &operator=(const DialogConnection &) = delete; + DialogConnection(DialogConnection &&) = delete; + DialogConnection &operator=(DialogConnection &&) = delete; + void OnAbilityConnectDone( + const AppExecFwk::ElementName &element, const sptr &remoteObject, int32_t resultCode) override; + void OnAbilityDisconnectDone(const AppExecFwk::ElementName &element, int32_t resultCode) override; + +private: + PasteBoardDialog::Cancel cancel_; +}; + +void DialogConnection::OnAbilityConnectDone( + const AppExecFwk::ElementName &element, const sptr &remoteObject, int32_t resultCode) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "dialog ability connected"); +} + +void DialogConnection::OnAbilityDisconnectDone(const AppExecFwk::ElementName &element, int32_t resultCode) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "dialog ability disconnect"); + if (cancel_ != nullptr) { + cancel_(); + } +} + +PasteBoardDialog &PasteBoardDialog::GetInstance() +{ + static PasteBoardDialog instance; + return instance; +} + +int32_t PasteBoardDialog::ShowToast(const ToastMessageInfo &message) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "begin, fromApp:%{public}s, toApp:%{public}s", + message.fromAppName.c_str(), message.toAppName.c_str()); + auto abilityManager = GetAbilityManagerService(); + if (abilityManager == nullptr) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "get ability manager failed"); + return -1; + } + Want want; + want.SetAction(""); + want.SetElementName(PASTEBOARD_DIALOG_APP, PASTEBOARD_TOAST_ABILITY); + want.SetParam("fromAppName", message.fromAppName); + want.SetParam("toAppName", message.toAppName); + + std::lock_guard lock(connectionLock_); + connection_ = new DialogConnection(nullptr); + int32_t result = IN_PROCESS_CALL(abilityManager->ConnectAbility(want, connection_, nullptr)); + if (result != 0) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "start pasteboard toast failed, result:%{public}d", result); + return -1; + } + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "start pasteboard toast success."); + return 0; +} + +void PasteBoardDialog::CancelToast() +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "begin"); + auto abilityManager = GetAbilityManagerService(); + if (abilityManager == nullptr) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "get ability manager failed"); + return; + } + std::lock_guard lock(connectionLock_); + int result = IN_PROCESS_CALL(abilityManager->DisconnectAbility(connection_)); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "disconnect toast ability:%{public}d", result); +} + +sptr PasteBoardDialog::GetAbilityManagerService() +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "begin"); + auto systemAbilityManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (systemAbilityManager == nullptr) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "failed to get samgr"); + return nullptr; + } + + sptr remoteObject = systemAbilityManager->GetSystemAbility(ABILITY_MGR_SERVICE_ID); + if (!remoteObject) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "failed to get ability manager service"); + return nullptr; + } + return iface_cast(remoteObject); +} +} // namespace OHOS::MiscServices diff --git a/pasteboard/services/core/src/pasteboard_service.cpp b/pasteboard/services/core/src/pasteboard_service.cpp new file mode 100644 index 00000000..9283d808 --- /dev/null +++ b/pasteboard/services/core/src/pasteboard_service.cpp @@ -0,0 +1,1525 @@ +/* + * Copyright (C) 2021-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "pasteboard_service.h" + +#include +#include + +#include "ability_manager_client.h" +#include "accesstoken_kit.h" +#include "account_manager.h" +#include "calculate_time_consuming.h" +#include "common_event_manager.h" +#include "common/block_object.h" +#include "dev_manager.h" +#include "dev_profile.h" +#include "device/dm_adapter.h" +#include "dfx_code_constant.h" +#include "dfx_types.h" +#include "distributed_file_daemon_manager.h" +#include "distributed_module_config.h" +#include "hiview_adapter.h" +#include "input_method_controller.h" +#include "iservice_registry.h" +#include "loader.h" +#include "int_wrapper.h" +#include "native_token_info.h" +#include "os_account_manager.h" +#include "para_handle.h" +#include "pasteboard_dialog.h" +#include "pasteboard_error.h" +#include "pasteboard_trace.h" +#include "remote_file_share.h" +#include "reporter.h" +#include "tokenid_kit.h" +#include "uri_permission_manager_client.h" +#ifdef SCENE_BOARD_ENABLE +#include "window_manager_lite.h" +#else +#include "window_manager.h" +#endif + +#ifdef WITH_DLP +#include "dlp_permission_kit.h" +#endif // WITH_DLP + +namespace OHOS { +namespace MiscServices { +using namespace Rosen; +using namespace std::chrono; +using namespace Storage::DistributedFile; +namespace { +constexpr const int GET_WRONG_SIZE = 0; +constexpr const size_t MAX_URI_COUNT = 500; +constexpr const int32_t COMMON_USERID = 0; +const std::int32_t INIT_INTERVAL = 10000L; +const std::string PASTEBOARD_SERVICE_NAME = "PasteboardService"; +const std::string FAIL_TO_GET_TIME_STAMP = "FAIL_TO_GET_TIME_STAMP"; +const std::string PASTEBOARD_PROXY_AUTHOR_URI = "ohos.permission.PROXY_AUTHORIZATION_URI"; +const std::string SECURE_PASTE_PERMISSION = "ohos.permission.SECURE_PASTE"; +const std::int32_t CALL_UID = 5557; +const bool G_REGISTER_RESULT = SystemAbility::MakeAndRegisterAbility(new PasteboardService()); +} // namespace +using namespace Security::AccessToken; +using namespace OHOS::AppFileService::ModuleRemoteFileShare; +std::mutex PasteboardService::historyMutex_; +std::vector PasteboardService::dataHistory_; +std::shared_ptr PasteboardService::copyHistory; +std::shared_ptr PasteboardService::copyData; +int32_t PasteboardService::currentUserId = ERROR_USERID; + +PasteboardService::PasteboardService() + : SystemAbility(PASTEBOARD_SERVICE_ID, true), state_(ServiceRunningState::STATE_NOT_START) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "PasteboardService Start."); + ServiceListenerFunc_[static_cast(DISTRIBUTED_HARDWARE_DEVICEMANAGER_SA_ID)] = + &PasteboardService::DevManagerInit; + ServiceListenerFunc_[static_cast(DISTRIBUTED_DEVICE_PROFILE_SA_ID)] = &PasteboardService::DevProfileInit; +} + +PasteboardService::~PasteboardService() +{ +} + +int32_t PasteboardService::Init() +{ + if (!Publish(this)) { + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "OnStart register to system ability manager failed."); + auto userId = GetCurrentAccountId(); + Reporter::GetInstance().PasteboardFault().Report({ userId, "ERR_INVALID_OPTION" }); + return static_cast(PasteboardError::E_INVALID_OPTION); + } + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "Init Success."); + state_ = ServiceRunningState::STATE_RUNNING; + return ERR_OK; +} + +void PasteboardService::OnStart() +{ + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "PasteboardService OnStart."); + if (state_ == ServiceRunningState::STATE_RUNNING) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "PasteboardService is already running."); + return; + } + + InitServiceHandler(); + auto appInfo = GetAppInfo(IPCSkeleton::GetCallingTokenID()); + Loader loader; + loader.LoadComponents(); + DMAdapter::GetInstance().Initialize(appInfo.bundleName); + DistributedModuleConfig::Watch(std::bind(&PasteboardService::OnConfigChange, this, std::placeholders::_1)); + + AddSysAbilityListener(); + + if (Init() != ERR_OK) { + auto callback = [this]() { Init(); }; + serviceHandler_->PostTask(callback, INIT_INTERVAL); + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "Init failed. Try again 10s later."); + return; + } + + copyHistory = std::make_shared(std::vector{ "--copy-history" }, + "Dump access history last ten times.", + [this](const std::vector &input, std::string &output) -> bool { + output = DumpHistory(); + return true; + }); + + copyData = std::make_shared(std::vector{ "--data" }, "Show copy data details.", + [this](const std::vector &input, std::string &output) -> bool { + output = DumpData(); + return true; + }); + + PasteboardDumpHelper::GetInstance().RegisterCommand(copyHistory); + PasteboardDumpHelper::GetInstance().RegisterCommand(copyData); + + if (commonEventSubscriber_ == nullptr) { + EventFwk::MatchingSkills matchingSkills; + matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_USER_SWITCHED); + EventFwk::CommonEventSubscribeInfo subscribeInfo(matchingSkills); + commonEventSubscriber_ = std::make_shared(subscribeInfo); + EventFwk::CommonEventManager::SubscribeCommonEvent(commonEventSubscriber_); + } + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "Start PasteboardService success."); + HiViewAdapter::StartTimerThread(); + return; +} + +void PasteboardService::OnStop() +{ + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "OnStop Started."); + if (state_ != ServiceRunningState::STATE_RUNNING) { + return; + } + serviceHandler_ = nullptr; + state_ = ServiceRunningState::STATE_NOT_START; + + ParaHandle::GetInstance().WatchEnabledStatus(nullptr); + DevManager::GetInstance().UnregisterDevCallback(); + if (commonEventSubscriber_ != nullptr) { + EventFwk::CommonEventManager::UnSubscribeCommonEvent(commonEventSubscriber_); + } + + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "OnStop End."); +} + +void PasteboardService::AddSysAbilityListener() +{ + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "begin."); + for (uint32_t i = 0; i < sizeof(LISTENING_SERVICE) / sizeof(LISTENING_SERVICE[0]); i++) { + auto ret = AddSystemAbilityListener(LISTENING_SERVICE[i]); + PASTEBOARD_HILOGD( + PASTEBOARD_MODULE_SERVICE, "ret = %{public}d, serviceId = %{public}d.", ret, LISTENING_SERVICE[i]); + } +} + +void PasteboardService::OnAddSystemAbility(int32_t systemAbilityId, const std::string &deviceId) +{ + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "systemAbilityId = %{public}d added!", systemAbilityId); + auto itFunc = ServiceListenerFunc_.find(systemAbilityId); + if (itFunc != ServiceListenerFunc_.end()) { + auto ServiceListenerFunc = itFunc->second; + if (ServiceListenerFunc != nullptr) { + (this->*ServiceListenerFunc)(); + } + } +} + +void PasteboardService::DevManagerInit() +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "begin."); + DevManager::GetInstance().Init(); +} + +void PasteboardService::DevProfileInit() +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "begin."); + ParaHandle::GetInstance().Init(); + DevProfile::GetInstance().Init(); +} + +void PasteboardService::InitServiceHandler() +{ + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "InitServiceHandler started."); + if (serviceHandler_ != nullptr) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "Already init."); + return; + } + std::shared_ptr runner = AppExecFwk::EventRunner::Create(PASTEBOARD_SERVICE_NAME); + serviceHandler_ = std::make_shared(runner); + + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "InitServiceHandler Succeeded."); +} + +void PasteboardService::Clear() +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "start."); + auto userId = GetCurrentAccountId(); + if (userId == ERROR_USERID) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "userId invalid."); + return; + } + std::lock_guard lock(clipMutex_); + auto it = clips_.find(userId); + if (it != clips_.end()) { + RevokeUriPermission(*(it->second)); + clips_.erase(it); + auto appInfo = GetAppInfo(IPCSkeleton::GetCallingTokenID()); + std::string bundleName = GetAppBundleName(appInfo); + NotifyObservers(bundleName, PasteboardEventStatus::PASTEBOARD_CLEAR); + } + auto hintItem = hints_.find(userId); + if (hintItem != hints_.end()) { + hints_.erase(hintItem); + } + CleanDistributedData(userId); +} + +bool PasteboardService::IsDefaultIME(const AppInfo &appInfo) +{ + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "start."); + if (appInfo.tokenType != ATokenTypeEnum::TOKEN_HAP) { + return true; + } + std::shared_ptr property = InputMethodController::GetInstance()->GetCurrentInputMethod(); + return property != nullptr && property->name == appInfo.bundleName; +} + +bool PasteboardService::IsFocusedApp(uint32_t tokenId) +{ + FocusChangeInfo info; +#ifdef SCENE_BOARD_ENABLE + WindowManagerLite::GetInstance().GetFocusWindowInfo(info); +#else + WindowManager::GetInstance().GetFocusWindowInfo(info); +#endif + auto callPid = IPCSkeleton::GetCallingPid(); + if (callPid == info.pid_) { + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "pid is same, focused app"); + return true; + } + bool isFocused = false; + auto ret = AAFwk::AbilityManagerClient::GetInstance()->CheckUIExtensionIsFocused(tokenId, isFocused); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "check result:%{public}d, isFocused:%{public}d", ret, isFocused); + return ret == ErrorCode::NO_ERROR && isFocused; +} + +bool PasteboardService::HasPastePermission( + uint32_t tokenId, bool isFocusedApp, const std::shared_ptr &pasteData) +{ + if (pasteData == nullptr || pasteData->IsDraggedData() || !pasteData->IsValid()) { + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "data is invalid"); + return false; + } + auto isPrivilegeApp = IsDefaultIME(GetAppInfo(tokenId)); + auto isGrantPermission = IsPermissionGranted(SECURE_PASTE_PERMISSION, tokenId); + if (!isFocusedApp && !isPrivilegeApp && !isGrantPermission) { + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "token:0x%{public}x", tokenId); + return false; + } + switch (pasteData->GetShareOption()) { + case ShareOption::InApp: { + if (pasteData->GetTokenId() != tokenId) { + PASTEBOARD_HILOGW(PASTEBOARD_MODULE_SERVICE, "InApp check failed."); + return false; + } + break; + } + case ShareOption::LocalDevice: { + break; + } + case ShareOption::CrossDevice: { + break; + } + default: { + PASTEBOARD_HILOGE( + PASTEBOARD_MODULE_SERVICE, "shareOption = %{public}d is error.", pasteData->GetShareOption()); + return false; + } + } + auto isDataAged = IsDataAged(); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "IsDataAged = %{public}d", isDataAged); + return isDataAged; +} + +bool PasteboardService::IsPermissionGranted(const std::string& perm, uint32_t tokenId) +{ + ATokenTypeEnum type = AccessTokenKit::GetTokenTypeFlag(tokenId); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "check grant permission, perm=%{public}s type=%{public}d", + perm.c_str(), type); + int32_t result = PermissionState::PERMISSION_DENIED; + switch (type) { + case ATokenTypeEnum::TOKEN_HAP: + result = AccessTokenKit::VerifyAccessToken(tokenId, perm); + break; + case ATokenTypeEnum::TOKEN_NATIVE: + case ATokenTypeEnum::TOKEN_SHELL: + result = PermissionState::PERMISSION_GRANTED; + break; + case ATokenTypeEnum::TOKEN_INVALID: + case ATokenTypeEnum::TOKEN_TYPE_BUTT: + break; + default: + break; + } + if (result == PermissionState::PERMISSION_DENIED) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "permission denied"); + return false; + } + return true; +} + +bool PasteboardService::IsDataAged() +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "IsDataAged start"); + auto userId = GetCurrentAccountId(); + if (userId == ERROR_USERID) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "userId invalid."); + return false; + } + auto it = copyTime_.find(userId); + if (it == copyTime_.end()) { + return false; + } + uint64_t copyTime = it->second; + auto curTime = static_cast(duration_cast(system_clock::now().time_since_epoch()).count()); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "copyTime = %{public}" PRIu64, copyTime); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "curTime = %{public}" PRIu64, curTime); + if (curTime > copyTime && curTime - copyTime > ONE_HOUR_MILLISECONDS) { + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "data is out of the time"); + auto data = clips_.find(userId); + if (data != clips_.end()) { + clips_.erase(data); + } + copyTime_.erase(it); + return false; + } + return true; +} + +AppInfo PasteboardService::GetAppInfo(uint32_t tokenId) +{ + AppInfo info; + info.tokenId = tokenId; + info.tokenType = AccessTokenKit::GetTokenTypeFlag(tokenId); + info.userId = GetCurrentAccountId(); + switch (info.tokenType) { + case ATokenTypeEnum::TOKEN_HAP: { + HapTokenInfo hapInfo; + if (AccessTokenKit::GetHapTokenInfo(tokenId, hapInfo) != 0) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "get hap token info fail."); + return info; + } + info.bundleName = hapInfo.bundleName; + break; + } + case ATokenTypeEnum::TOKEN_NATIVE: + case ATokenTypeEnum::TOKEN_SHELL: { + NativeTokenInfo tokenInfo; + if (AccessTokenKit::GetNativeTokenInfo(tokenId, tokenInfo) != 0) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "get native token info fail."); + return info; + } + info.bundleName = tokenInfo.processName; + break; + } + default: { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "tokenType = %{public}d not match.", info.tokenType); + } + } + return info; +} + +std::string PasteboardService::GetAppBundleName(const AppInfo &appInfo) +{ + std::string bundleName; + if (appInfo.userId != ERROR_USERID) { + bundleName = appInfo.bundleName; + } else { + bundleName = "error"; + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "GetAppInfo error"); + } + return bundleName; +} + +void PasteboardService::SetLocalPasteFlag(bool isCrossPaste, uint32_t tokenId, PasteData &pasteData) +{ + pasteData.SetLocalPasteFlag(!isCrossPaste && tokenId == pasteData.GetTokenId()); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "isLocalPaste = %{public}d.", pasteData.IsLocalPaste()); +} + +int32_t PasteboardService::GetPasteData(PasteData &data) +{ + CalculateTimeConsuming::SetBeginTime(); + + PasteboardTrace tracer("PasteboardService GetPasteData"); + + auto tokenId = IPCSkeleton::GetCallingTokenID(); + auto appInfo = GetAppInfo(tokenId); + bool isFocusedApp = IsFocusedApp(tokenId); + bool result = false; + auto clipPlugin = GetClipPlugin(); + if (clipPlugin == nullptr) { + result = CheckPasteData(appInfo, data, isFocusedApp); + } else { + std::lock_guard lock(remoteMutex_); + result = GetRemoteData(appInfo, data, isFocusedApp); + } + if (observerEventMap_.size() != 0) { + std::string targetBundleName = GetAppBundleName(appInfo); + NotifyObservers(targetBundleName, PasteboardEventStatus::PASTEBOARD_READ); + } + GetPasteDataDot(data, appInfo.bundleName); + GrantUriPermission(data, appInfo.bundleName); + return result ? static_cast(PasteboardError::E_OK) : static_cast(PasteboardError::E_ERROR); +} + +bool PasteboardService::GetRemoteData(AppInfo &appInfo, PasteData &data, bool isFocusedApp) +{ + auto block = std::make_shared>>(PasteBoardDialog::POPUP_INTERVAL); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "start"); + std::thread thread([this, block, isFocusedApp, &appInfo]() mutable { + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "GetPasteData Begin"); + std::shared_ptr pasteData = std::make_shared(); + auto success = GetPasteData(appInfo, *pasteData, isFocusedApp); + if (!success) { + pasteData->SetInvalid(); + } + block->SetValue(pasteData); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "GetPasteData End"); + }); + thread.detach(); + auto value = block->GetValue(); + if (value == nullptr) { + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "continue to get remote data"); + block->SetInterval(PasteBoardDialog::MAX_LIFE_TIME); + value = block->GetValue(); + } + if (value != nullptr) { + auto ret = value->IsValid(); + data = std::move(*value); + return ret; + } + return false; +} + +bool PasteboardService::GetPasteData(AppInfo &appInfo, PasteData &data, bool isFocusedApp) +{ + PasteboardTrace tracer("GetPasteData inner"); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "start inner."); + if (appInfo.userId == ERROR_USERID) { + PasteData::sharePath = ""; + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "userId error."); + return false; + } + PasteData::sharePath = PasteData::SHARE_PATH_PREFIX + std::to_string(appInfo.userId) + + PasteData::SHARE_PATH_PREFIX_ACCOUNT; + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "Clips length %{public}d.", static_cast(clips_.size())); + bool isRemote = false; + std::lock_guard lock(clipMutex_); + auto pastData = GetDistributedData(appInfo.userId); + if (pastData != nullptr) { + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "pastData != nullptr"); + isRemote = true; + pastData->SetRemote(isRemote); + clips_.insert_or_assign(appInfo.userId, pastData); + auto curTime = + static_cast(duration_cast(system_clock::now().time_since_epoch()).count()); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "curTime = %{public}" PRIu64, curTime); + copyTime_.insert_or_assign(appInfo.userId, curTime); + } + data.SetRemote(isRemote); + return CheckPasteData(appInfo, data, isFocusedApp); +} + +bool PasteboardService::CheckPasteData(AppInfo &appInfo, PasteData &data, bool isFocusedApp) +{ + { + std::lock_guard lock(clipMutex_); + auto it = clips_.find(appInfo.userId); + if (it == clips_.end()) { + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "no data."); + return false; + } + auto ret = HasPastePermission(appInfo.tokenId, isFocusedApp, it->second); + if (!ret) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "don't have paste permission."); + return false; + } + it->second->SetBundleName(appInfo.bundleName); + data = *(it->second); + } + auto fileSize = data.GetProperty().additions.GetIntParam(PasteData::REMOTE_FILE_SIZE, -1); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "isRemote=%{public}d, fileSize=%{public}d", + data.IsRemote(), fileSize); + if (data.IsRemote() && fileSize > 0) { + EstablishP2PLink(); + } + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "GetPasteData success."); + SetLocalPasteFlag(data.IsRemote(), appInfo.tokenId, data); + return true; +} + +void PasteboardService::EstablishP2PLink() +{ +#ifdef PB_DEVICE_MANAGER_ENABLE + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "EstablishP2PLink"); + DmDeviceInfo remoteDevice; + auto ret = DMAdapter::GetInstance().GetRemoteDeviceInfo(currentEvent_.deviceId, remoteDevice); + if (ret != RESULT_OK) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "remote device is not exist"); + return; + } + DistributedFileDaemonManager::GetInstance().OpenP2PConnection(remoteDevice); + auto it = p2pMap_.find(currentEvent_.deviceId); + if (it != p2pMap_.end() && it->second == 1) { + return; + } + p2pMap_.insert_or_assign(currentEvent_.deviceId, 1); + std::thread thread([this, remoteDevice]() mutable { + std::this_thread::sleep_for(std::chrono::seconds(MIN_TRANMISSION_TIME)); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "CloseP2PLink"); + DistributedFileDaemonManager::GetInstance().CloseP2PConnection(remoteDevice); + p2pMap_.erase(currentEvent_.deviceId); + }); + thread.detach(); +#endif +} + +void PasteboardService::GrantUriPermission(PasteData &data, const std::string &targetBundleName) +{ + std::vector grantUris; + CheckUriPermission(data, grantUris, targetBundleName); + if (grantUris.size() == 0) { + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "no uri."); + return; + } + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "uri size: %{public}u, targetBundleName is %{public}s", + static_cast(grantUris.size()), targetBundleName.c_str()); + auto& permissionClient = AAFwk::UriPermissionManagerClient::GetInstance(); + size_t index = grantUris.size() / MAX_URI_COUNT; + if (index == 0) { + auto permissionCode = permissionClient.GrantUriPermission(grantUris, AAFwk::Want::FLAG_AUTH_READ_URI_PERMISSION, + targetBundleName); + if (permissionCode == 0 && readBundles_.count(targetBundleName) == 0) { + readBundles_.insert(targetBundleName); + } + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "permissionCode is %{public}d", permissionCode); + return; + } + size_t remainder = grantUris.size() % MAX_URI_COUNT; + for (size_t i = 0; i <= index; i++) { + std::vector partUrs; + std::vector::const_iterator start = grantUris.begin() + i * MAX_URI_COUNT; + std::vector::const_iterator end; + if (i < index) { + end = grantUris.begin() + i * MAX_URI_COUNT + MAX_URI_COUNT; + } else { + end = grantUris.begin() + i * MAX_URI_COUNT + remainder; + } + if (start == end) { + continue; + } + partUrs.assign(start, end); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "grant uri size:%{public}u", + static_cast(partUrs.size())); + auto permissionCode = permissionClient.GrantUriPermission(partUrs, AAFwk::Want::FLAG_AUTH_READ_URI_PERMISSION, + targetBundleName); + if (permissionCode == 0 && readBundles_.count(targetBundleName) == 0) { + readBundles_.insert(targetBundleName); + } + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "permissionCode is %{public}d", permissionCode); + } +} + +void PasteboardService::CheckUriPermission(PasteData &data, std::vector &grantUris, + const std::string &targetBundleName) +{ + for (size_t i = 0; i < data.GetRecordCount(); i++) { + auto item = data.GetRecordAt(i); + if (item == nullptr || (!data.IsRemote() && targetBundleName.compare(data.GetOrginAuthority()) == 0)) { + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "local dev & local app"); + continue; + } + std::shared_ptr uri = nullptr; + if (!item->isConvertUriFromRemote && !item->GetConvertUri().empty()) { + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "clear local disUri"); + item->SetConvertUri(""); + } + if (item->isConvertUriFromRemote && !item->GetConvertUri().empty()) { + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "get remote disUri"); + uri = std::make_shared(item->GetConvertUri()); + } else if (!item->isConvertUriFromRemote && item->GetOrginUri() != nullptr) { + uri = item->GetOrginUri(); + } + auto hasGrantUriPermission = item->HasGrantUriPermission(); + if (uri == nullptr || (!isBundleOwnUriPermission(data.GetOrginAuthority(), *uri) && !hasGrantUriPermission)) { + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "uri is null:%{public}d, not grant permission: %{public}d.", + uri == nullptr, hasGrantUriPermission); + continue; + } + grantUris.emplace_back(*uri); + } +} + +void PasteboardService::RevokeUriPermission(PasteData &lastData) +{ + if (readBundles_.size() == 0) { + return; + } + auto& permissionClient = AAFwk::UriPermissionManagerClient::GetInstance(); + for (size_t i = 0; i < lastData.GetRecordCount(); i++) { + auto item = lastData.GetRecordAt(i); + if (item == nullptr || item->GetOrginUri() == nullptr) { + continue; + } + Uri uri = *(item->GetOrginUri()); + for (std::set::iterator it = readBundles_.begin(); it != readBundles_.end(); it++) { + auto permissionCode = permissionClient.RevokeUriPermissionManually(uri, *it); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "permissionCode is %{public}d", permissionCode); + } + } + readBundles_.clear(); +} + +bool PasteboardService::isBundleOwnUriPermission(const std::string &bundleName, Uri &uri) +{ + auto authority = uri.GetAuthority(); + if (bundleName.compare(authority) != 0) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "grant error, uri:%{public}s, orgin:%{public}s", + authority.c_str(), bundleName.c_str()); + return false; + } + return true; +} + +void PasteboardService::CheckAppUriPermission(PasteData &data) +{ + for (size_t i = 0; i < data.GetRecordCount(); i++) { + auto item = data.GetRecordAt(i); + if (item == nullptr || item->GetOrginUri() == nullptr) { + continue; + } + auto uri = item->GetOrginUri(); + int32_t ret = Security::AccessToken::AccessTokenKit::VerifyAccessToken(data.GetTokenId(), + PASTEBOARD_PROXY_AUTHOR_URI); + if (ret != Security::AccessToken::PermissionState::PERMISSION_GRANTED) { + item->SetGrantUriPermission(false); + continue; + } + item->SetGrantUriPermission(true); + } +} + +void PasteboardService::ShowHintToast(bool isValid, uint32_t tokenId, const std::shared_ptr &pasteData) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "show hint toast start"); + if (!isValid || pasteData == nullptr || pasteData->IsDraggedData()) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "data is invalid"); + return; + } + auto dataTokenId = pasteData->GetTokenId(); + if (IsDefaultIME(GetAppInfo(tokenId)) || dataTokenId == tokenId || pasteData->IsRemote()) { + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "not need show hint toast"); + return; + } + auto userId = GetCurrentAccountId(); + auto hintItem = hints_.find(userId); + if (hintItem != hints_.end()) { + auto hintTokenId = std::find(hintItem->second.begin(), hintItem->second.end(), tokenId); + if (hintTokenId != hintItem->second.end()) { + return; + } + } + hints_[userId].emplace_back(tokenId); + + PasteBoardDialog::ToastMessageInfo message; + message.fromAppName = GetAppLabel(dataTokenId); + message.toAppName = GetAppLabel(tokenId); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "toast should show, fromName=%{public}s, toName = %{public}s", + message.fromAppName.c_str(), message.toAppName.c_str()); + std::thread thread([this, message]() mutable { + PasteBoardDialog::GetInstance().ShowToast(message); + std::this_thread::sleep_for(std::chrono::milliseconds(PasteBoardDialog::SHOW_TOAST_TIME)); + PasteBoardDialog::GetInstance().CancelToast(); + }); + thread.detach(); +} + +bool PasteboardService::HasPasteData() +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "start."); + auto userId = GetCurrentAccountId(); + if (userId == ERROR_USERID) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "userId invalid."); + return false; + } + std::lock_guard lock(clipMutex_); + auto it = clips_.find(userId); + if (it == clips_.end()) { + return HasDistributedData(userId); + } + + auto tokenId = IPCSkeleton::GetCallingTokenID(); + return HasPastePermission(tokenId, IsFocusedApp(tokenId), it->second); +} + +int32_t PasteboardService::SetPasteData(PasteData &pasteData) +{ + auto data = std::make_shared(pasteData); + return SavePasteData(data); +} + +bool PasteboardService::HasDataType(const std::string &mimeType) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "start."); + auto clipPlugin = GetClipPlugin(); + if (clipPlugin == nullptr) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "clipPlugin null."); + return HasLocalDataType(mimeType); + } + auto userId = GetCurrentAccountId(); + ClipPlugin::GlobalEvent event; + auto isEffective = GetDistributedEvent(clipPlugin, userId, event); + if (!isEffective || event == currentEvent_) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "EVT_UNKNOWN."); + return HasLocalDataType(mimeType); + } + HasDistributedData(userId); + return HasDistributedDataType(mimeType); +} + +bool PasteboardService::HasLocalDataType(const std::string &mimeType) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "start."); + auto hasData = HasPasteData(); + if (!hasData) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "data is not exist"); + return false; + } + auto userId = GetCurrentAccountId(); + std::lock_guard lock(clipMutex_); + auto it = clips_.find(userId); + if (it == clips_.end()) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "can not find data"); + return false; + } + if (it->second == nullptr) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "data is nullptr"); + return false; + } + std::vector mimeTypes = it->second->GetMimeTypes(); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "type is %{public}s", mimeType.c_str()); + auto isWebData = it->second->GetTag() == PasteData::WEBVIEW_PASTEDATA_TAG; + auto isExistType = std::find(mimeTypes.begin(), mimeTypes.end(), mimeType) != mimeTypes.end(); + if (isWebData) { + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "is Web Data"); + return mimeType == MIMETYPE_TEXT_HTML && isExistType; + } + return isExistType; +} + +bool PasteboardService::HasDistributedDataType(const std::string &mimeType) +{ + auto value = remoteEvent_.dataType; + std::bitset dataType(value); + auto it = typeMap_.find(mimeType); + if (it == typeMap_.end()) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "mimetype is not exist"); + return false; + } + auto index = it->second; + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "index = %{public}d", index); + return dataType[index]; +} + +bool PasteboardService::IsRemoteData() +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "start."); + auto userId = GetCurrentAccountId(); + if (userId == ERROR_USERID) { + return false; + } + std::lock_guard lock(clipMutex_); + auto it = clips_.find(userId); + if (it == clips_.end()) { + return HasDistributedData(userId); + } + return it->second->IsRemote(); +} + +int32_t PasteboardService::GetDataSource(std::string &bundleName) +{ + auto userId = GetCurrentAccountId(); + if (userId == ERROR_USERID) { + return static_cast(PasteboardError::E_ERROR); + } + std::lock_guard lock(clipMutex_); + auto it = clips_.find(userId); + if (it == clips_.end()) { + return static_cast(PasteboardError::E_REMOTE); + } + auto data = it->second; + if (data->IsRemote()) { + return static_cast(PasteboardError::E_REMOTE); + } + auto tokenId = data->GetTokenId(); + bundleName = GetAppLabel(tokenId); + return static_cast(PasteboardError::E_OK); +} + +int32_t PasteboardService::SavePasteData(std::shared_ptr &pasteData) +{ + PasteboardTrace tracer("PasteboardService, SetPasteData"); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "start."); + auto tokenId = IPCSkeleton::GetCallingTokenID(); + if (!IsCopyable(tokenId)) { + return static_cast(PasteboardError::E_COPY_FORBIDDEN); + } + if (setting_.exchange(true)) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "is setting."); + return static_cast(PasteboardError::E_IS_BEGING_PROCESSED); + } + CalculateTimeConsuming::SetBeginTime(); + auto appInfo = GetAppInfo(tokenId); + if (appInfo.userId == ERROR_USERID) { + setting_.store(false); + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "userId invalid."); + return static_cast(PasteboardError::E_ERROR); + } + std::lock_guard lock(clipMutex_); + auto it = clips_.find(appInfo.userId); + if (it != clips_.end()) { + RevokeUriPermission(*(it->second)); + clips_.erase(it); + } + pasteData->SetBundleName(appInfo.bundleName); + pasteData->SetOrginAuthority(appInfo.bundleName); + std::string time = GetTime(); + pasteData->SetTime(time); + pasteData->SetTokenId(tokenId); + CheckAppUriPermission(*pasteData); + SetWebViewPasteData(*pasteData, appInfo.bundleName); + clips_.insert_or_assign(appInfo.userId, pasteData); + auto curTime = static_cast(duration_cast(system_clock::now().time_since_epoch()).count()); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "curTime = %{public}" PRIu64, curTime); + copyTime_.insert_or_assign(appInfo.userId, curTime); + SetDistributedData(appInfo.userId, *pasteData); + NotifyObservers(appInfo.bundleName, PasteboardEventStatus::PASTEBOARD_WRITE); + SetPasteDataDot(*pasteData); + auto hintItem = hints_.find(appInfo.userId); + if (hintItem != hints_.end()) { + hints_.erase(hintItem); + } + setting_.store(false); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "Clips length %{public}d.", static_cast(clips_.size())); + return static_cast(PasteboardError::E_OK); +} + +void PasteboardService::SetWebViewPasteData(PasteData &pasteData, const std::string &bundleName) +{ + if (pasteData.GetTag() != PasteData::WEBVIEW_PASTEDATA_TAG) { + return; + } + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "PasteboardService for webview."); + for (auto& item : pasteData.AllRecords()) { + if (item->GetUri() == nullptr) { + continue; + } + std::shared_ptr uri = item->GetUri(); + std::string puri = uri->ToString(); + if (puri.substr(0, PasteData::IMG_LOCAL_URI.size()) == PasteData::IMG_LOCAL_URI && + puri.find(PasteData::FILE_SCHEME_PREFIX + PasteData::PATH_SHARE) == std::string::npos) { + std::string path = uri->GetPath(); + std::string newUriStr = PasteData::FILE_SCHEME_PREFIX + bundleName + path; + item->SetUri(std::make_shared(newUriStr)); + } + } +} + +int32_t PasteboardService::GetCurrentAccountId() +{ + if (currentUserId != ERROR_USERID) { + return currentUserId; + } + std::vector accountIds; + auto ret = AccountSA::OsAccountManager::QueryActiveOsAccountIds(accountIds); + if (ret != ERR_OK || accountIds.empty()) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "query active user failed errCode=%{public}d", ret); + return ERROR_USERID; + } + currentUserId = accountIds.front(); + return currentUserId; +} + +bool PasteboardService::IsCopyable(uint32_t tokenId) const +{ +#ifdef WITH_DLP + bool copyable = false; + auto ret = Security::DlpPermission::DlpPermissionKit::QueryDlpFileCopyableByTokenId(copyable, tokenId); + if (ret != 0 || !copyable) { + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "tokenId = 0x%{public}x ret = %{public}d, copyable = %{public}d.", + tokenId, ret, copyable); + return false; + } +#endif + return true; +} + +void PasteboardService::AddPasteboardChangedObserver(const sptr &observer) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "start."); + AddObserver(observer, observerChangedMap_); +} + +void PasteboardService::RemovePasteboardChangedObserver(const sptr &observer) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "start."); + RemoveSingleObserver(observer, observerChangedMap_); +} + +void PasteboardService::RemoveAllChangedObserver() +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "start."); + RemoveAllObserver(observerChangedMap_); +} + +void PasteboardService::AddPasteboardEventObserver(const sptr &observer) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "start."); + if (!IsCallerUidValid()) { + return; + } + AddObserver(observer, observerEventMap_); +} + +void PasteboardService::RemovePasteboardEventObserver(const sptr &observer) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "start."); + if (!IsCallerUidValid()) { + return; + } + RemoveSingleObserver(observer, observerEventMap_); +} + +void PasteboardService::RemoveAllEventObserver() +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "start."); + if (!IsCallerUidValid()) { + return; + } + RemoveAllObserver(observerEventMap_); +} + +void PasteboardService::AddObserver(const sptr &observer, ObserverMap &observerMap) +{ + if (observer == nullptr) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "observer null."); + return; + } + std::lock_guard lock(observerMutex_); + auto it = observerMap.find(COMMON_USERID); + std::shared_ptr, classcomp>> observers; + if (it != observerMap.end()) { + observers = it->second; + } else { + observers = std::make_shared, classcomp>>(); + observerMap.insert(std::make_pair(COMMON_USERID, observers)); + } + observers->insert(observer); + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "observers->size = %{public}u.", + static_cast(observers->size())); +} + +void PasteboardService::RemoveSingleObserver(const sptr &observer, ObserverMap &observerMap) +{ + if (observer == nullptr) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "observer null."); + return; + } + std::lock_guard lock(observerMutex_); + auto it = observerMap.find(COMMON_USERID); + if (it == observerMap.end()) { + return; + } + auto observers = it->second; + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "observers size: %{public}u.", + static_cast(observers->size())); + auto eraseNum = observers->erase(observer); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "observers size = %{public}u, eraseNum = %{public}zu", + static_cast(observers->size()), eraseNum); +} + +void PasteboardService::RemoveAllObserver(ObserverMap &observerMap) +{ + std::lock_guard lock(observerMutex_); + auto it = observerMap.find(COMMON_USERID); + if (it == observerMap.end()) { + PASTEBOARD_HILOGW(PASTEBOARD_MODULE_SERVICE, "observer empty."); + return; + } + auto observers = it->second; + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "observers size: %{public}u.", + static_cast(observers->size())); + auto eraseNum = observerMap.erase(COMMON_USERID); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "observers size = %{public}u, eraseNum = %{public}zu", + static_cast(observers->size()), eraseNum); +} + +inline bool PasteboardService::IsCallerUidValid() +{ + pid_t callingUid = IPCSkeleton::GetCallingUid(); + if (callingUid == EDM_UID || callingUid == CALL_UID) { + return true; + } + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "callingUid error: %{public}d.", callingUid); + return false; +} + +void PasteboardService::NotifyObservers(std::string bundleName, PasteboardEventStatus status) +{ + std::thread thread([this, bundleName, status] () { + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "start."); + std::lock_guard lock(observerMutex_); + for (auto &observers : observerChangedMap_) { + for (const auto &observer : *(observers.second)) { + if (status != PasteboardEventStatus::PASTEBOARD_READ) { + observer->OnPasteboardChanged(); + } + } + } + for (auto &observers : observerEventMap_) { + for (const auto &observer : *(observers.second)) { + observer->OnPasteboardEvent(bundleName, static_cast(status)); + } + } + }); + thread.detach(); +} + +size_t PasteboardService::GetDataSize(PasteData &data) const +{ + if (data.GetRecordCount() != 0) { + size_t counts = data.GetRecordCount() - 1; + std::shared_ptr records = data.GetRecordAt(counts); + std::string text = records->ConvertToText(); + size_t textSize = text.size(); + return textSize; + } + return GET_WRONG_SIZE; +} + +bool PasteboardService::SetPasteboardHistory(HistoryInfo &info) +{ + std::string history = std::move(info.time) + " " + std::move(info.bundleName) + " " + std::move(info.state) + " " + + " " + std::move(info.remote); + constexpr const size_t DATA_HISTORY_SIZE = 10; + std::lock_guard lg(historyMutex_); + if (dataHistory_.size() == DATA_HISTORY_SIZE) { + dataHistory_.erase(dataHistory_.begin()); + } + dataHistory_.push_back(std::move(history)); + return true; +} + +int PasteboardService::Dump(int fd, const std::vector &args) +{ + int uid = static_cast(IPCSkeleton::GetCallingUid()); + const int maxUid = 10000; + if (uid > maxUid) { + return 0; + } + + std::vector argsStr; + for (auto item : args) { + argsStr.emplace_back(Str16ToStr8(item)); + } + + if (PasteboardDumpHelper::GetInstance().Dump(fd, argsStr)) { + return 0; + } + return 0; +} + +std::string PasteboardService::GetTime() +{ + constexpr int USEC_TO_MSEC = 1000; + time_t timeSeconds = time(0); + if (timeSeconds == -1) { + return FAIL_TO_GET_TIME_STAMP; + } + struct tm nowTime; + localtime_r(&timeSeconds, &nowTime); + + struct timeval timeVal = { 0, 0 }; + gettimeofday(&timeVal, nullptr); + + std::string targetTime = std::to_string(nowTime.tm_year + 1900) + "-" + std::to_string(nowTime.tm_mon + 1) + "-" + + std::to_string(nowTime.tm_mday) + " " + std::to_string(nowTime.tm_hour) + ":" + + std::to_string(nowTime.tm_min) + ":" + std::to_string(nowTime.tm_sec) + "." + + std::to_string(timeVal.tv_usec / USEC_TO_MSEC); + return targetTime; +} + +std::string PasteboardService::DumpHistory() const +{ + std::string result; + std::lock_guard lg(historyMutex_); + if (!dataHistory_.empty()) { + result.append("Access history last ten times: ").append("\n"); + for (auto iter = dataHistory_.rbegin(); iter != dataHistory_.rend(); ++iter) { + result.append(" ").append(*iter).append("\n"); + } + } else { + result.append("Access history fail! dataHistory_ no data.").append("\n"); + } + return result; +} + +std::string PasteboardService::DumpData() +{ + auto userId = GetCurrentAccountId(); + if (userId == ERROR_USERID) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "query active user failed."); + return ""; + } + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "id = %{public}d", userId); + std::lock_guard lock(clipMutex_); + auto it = clips_.find(userId); + std::string result; + if (it != clips_.end() && it->second != nullptr) { + size_t recordCounts = it->second->GetRecordCount(); + auto property = it->second->GetProperty(); + std::string shareOption; + PasteData::ShareOptionToString(property.shareOption, shareOption); + std::string sourceDevice; + if (property.isRemote) { + sourceDevice = "remote"; + } else { + sourceDevice = "local"; + } + result.append("|Owner : ") + .append(property.bundleName) + .append("\n") + .append("|Timestamp : ") + .append(property.setTime) + .append("\n") + .append("|Share Option: ") + .append(shareOption) + .append("\n") + .append("|Record Count: ") + .append(std::to_string(recordCounts)) + .append("\n") + .append("|Mime types : {"); + if (!property.mimeTypes.empty()) { + for (size_t i = 0; i < property.mimeTypes.size(); ++i) { + result.append(property.mimeTypes[i]).append(","); + } + } + result.append("}").append("\n").append("|source device: ").append(sourceDevice); + } else { + result.append("No copy data.").append("\n"); + } + return result; +} + +void PasteboardService::SetPasteDataDot(PasteData &pasteData) +{ + auto bundleName = pasteData.GetBundleName(); + HistoryInfo info{ pasteData.GetTime(), bundleName, "set", "" }; + SetPasteboardHistory(info); + + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "SetPasteData Report!"); + Reporter::GetInstance().PasteboardBehaviour().Report( + { static_cast(BehaviourPasteboardState::BPS_COPY_STATE), bundleName }); + + int state = static_cast(StatisticPasteboardState::SPS_COPY_STATE); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "SetPasteData GetDataSize!"); + size_t dataSize = GetDataSize(pasteData); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "SetPasteData timeC!"); + CalculateTimeConsuming timeC(dataSize, state); +} + +void PasteboardService::GetPasteDataDot(PasteData &pasteData, const std::string &bundleName) +{ + std::string remote; + if (pasteData.IsRemote()) { + remote = "remote"; + } + std::string time = GetTime(); + HistoryInfo info{ time, bundleName, "get", remote }; + SetPasteboardHistory(info); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "GetPasteData Report!"); + int pState = StatisticPasteboardState::SPS_INVALID_STATE; + int bState = BehaviourPasteboardState::BPS_INVALID_STATE; + if (pasteData.IsRemote()) { + pState = static_cast(StatisticPasteboardState::SPS_REMOTE_PASTE_STATE); + bState = static_cast(BehaviourPasteboardState::BPS_REMOTE_PASTE_STATE); + } else { + pState = static_cast(StatisticPasteboardState::SPS_PASTE_STATE); + bState = static_cast(BehaviourPasteboardState::BPS_PASTE_STATE); + }; + + Reporter::GetInstance().PasteboardBehaviour().Report({ bState, bundleName }); + + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "GetPasteData GetDataSize"); + size_t dataSize = GetDataSize(pasteData); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "GetPasteData timeC"); + CalculateTimeConsuming timeC(dataSize, pState); +} + +std::shared_ptr PasteboardService::GetDistributedData(int32_t user) +{ + auto clipPlugin = GetClipPlugin(); + if (clipPlugin == nullptr) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "clipPlugin null."); + return nullptr; + } + ClipPlugin::GlobalEvent event; + auto isEffective = GetDistributedEvent(clipPlugin, user, event); + if (event.status == ClipPlugin::EVT_UNKNOWN) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "EVT_UNKNOWN."); + return nullptr; + } + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "same device:%{public}d, evt seq:%{public}u current seq:%{public}u.", + event.deviceId == currentEvent_.deviceId, event.seqId, currentEvent_.seqId); + std::vector rawData = std::move(event.addition); + if (!isEffective) { + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "data is invalid"); + currentEvent_.status = ClipPlugin::EVT_INVALID; + currentEvent_ = std::move(event); + Reporter::GetInstance().PasteboardFault().Report({ user, "GET_REMOTE_DATA_FAILED" }); + return nullptr; + } + + if (event.frameNum > 0 && (clipPlugin->GetPasteData(event, rawData) != 0)) { + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "get data failed"); + Reporter::GetInstance().PasteboardFault().Report({ user, "GET_REMOTE_DATA_FAILED" }); + return nullptr; + } + + currentEvent_ = std::move(event); + std::shared_ptr pasteData = std::make_shared(); + pasteData->Decode(rawData); + pasteData->ReplaceShareUri(user); + pasteData->SetOrginAuthority(pasteData->GetBundleName()); + int fileSize = pasteData->GetProperty().additions.GetIntParam(PasteData::REMOTE_FILE_SIZE, -1); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "remote bundle: %{public}s", pasteData->GetBundleName().c_str()); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "remote file size: %{public}d", fileSize); + for (size_t i = 0; i < pasteData->GetRecordCount(); i++) { + auto item = pasteData->GetRecordAt(i); + if (item == nullptr || item->GetConvertUri().empty()) { + continue; + } + item->isConvertUriFromRemote = true; + } + return pasteData; +} + +bool PasteboardService::SetDistributedData(int32_t user, PasteData &data) +{ + std::shared_ptr> rawData = std::make_shared>(); + auto clipPlugin = GetClipPlugin(); + if (clipPlugin == nullptr) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "clipPlugin null."); + return false; + } + GenerateDistributedUri(data); + if (data.GetShareOption() != CrossDevice || !data.Encode(*rawData)) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "Cross-device data is not supported."); + return false; + } + + auto networkId = DMAdapter::GetInstance().GetLocalNetworkId(); + if (networkId.empty()) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "networkId is empty."); + return false; + } + + auto expiration = + duration_cast((system_clock::now() + minutes(EXPIRATION_INTERVAL)).time_since_epoch()).count(); + Event event; + event.user = user; + event.seqId = ++sequenceId_; + event.expiration = static_cast(expiration); + event.deviceId = networkId; + event.account = AccountManager::GetInstance().GetCurrentAccount(); + event.status = (data.GetShareOption() == CrossDevice) ? ClipPlugin::EVT_NORMAL : ClipPlugin::EVT_INVALID; + event.dataType = GenerateDataType(data); + currentEvent_ = event; + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "expiration = %{public}" PRIu64, event.expiration); + std::thread thread([clipPlugin, event, rawData]() mutable { + clipPlugin->SetPasteData(event, *rawData); + }); + thread.detach(); + return true; +} + +uint8_t PasteboardService::GenerateDataType(PasteData &data) +{ + std::vector mimeTypes = data.GetMimeTypes(); + if (mimeTypes.empty()) { + return 0; + } + std::bitset dataType(0); + for (size_t i = 0; i < mimeTypes.size(); i++) { + auto it = typeMap_.find(mimeTypes[i]); + if (it == typeMap_.end()) { + continue; + } + auto index = it->second; + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "mimetype is exist index=%{public}d", index); + if (it->second == HTML_INDEX && data.GetTag() == PasteData::WEBVIEW_PASTEDATA_TAG) { + dataType.reset(); + dataType.set(index); + break; + } + dataType.set(index); + } + auto types = dataType.to_ulong(); + uint8_t value = types & 0xff; + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "value = %{public}d", value); + return value; +} + +void PasteboardService::GenerateDistributedUri(PasteData &data) +{ + auto userId = GetCurrentAccountId(); + if (userId == ERROR_USERID) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "userId invalid."); + return; + } + size_t fileSize = 0; + for (size_t i = 0; i < data.GetRecordCount(); i++) { + auto item = data.GetRecordAt(i); + if (item == nullptr || item->GetOrginUri() == nullptr) { + continue; + } + Uri uri = *(item->GetOrginUri()); + if (!isBundleOwnUriPermission(data.GetOrginAuthority(), uri) && !item->HasGrantUriPermission()) { + continue; + } + HmdfsUriInfo hui; + auto ret = RemoteFileShare::GetDfsUriFromLocal(uri.ToString(), userId, hui); + if (ret != 0) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "creat uri failed: %{public}d", ret); + continue; + } + item->SetConvertUri(hui.uriStr); + fileSize += hui.fileSize; + } + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "file size: %{public}zu", fileSize); + data.SetAddition(PasteData::REMOTE_FILE_SIZE, AAFwk::Integer::Box(fileSize)); +} + +bool PasteboardService::HasDistributedData(int32_t user) +{ + auto clipPlugin = GetClipPlugin(); + if (clipPlugin == nullptr) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "clipPlugin null."); + return false; + } + Event event; + auto has = GetDistributedEvent(clipPlugin, user, event); + remoteEvent_ = std::move(event); + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "same device:%{public}d, evt seq:%{public}u current seq:%{public}u.", + event.deviceId == currentEvent_.deviceId, event.seqId, currentEvent_.seqId); + return has; +} + +std::shared_ptr PasteboardService::GetClipPlugin() +{ + auto isOn = DistributedModuleConfig::IsOn(); + std::lock_guard lockGuard(mutex); + if (!isOn || clipPlugin_ != nullptr) { + return clipPlugin_; + } + + auto release = [this](ClipPlugin *plugin) { + std::lock_guard lockGuard(mutex); + ClipPlugin::DestroyPlugin(PLUGIN_NAME, plugin); + }; + + clipPlugin_ = std::shared_ptr(ClipPlugin::CreatePlugin(PLUGIN_NAME), release); + return clipPlugin_; +} + +bool PasteboardService::CleanDistributedData(int32_t user) +{ + auto clipPlugin = GetClipPlugin(); + if (clipPlugin == nullptr) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "clipPlugin null."); + return true; + } + clipPlugin->Clear(user); + return true; +} + +void PasteboardService::OnConfigChange(bool isOn) +{ + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "ConfigChange isOn: %{public}d.", isOn); + p2pMap_.clear(); + std::lock_guard lockGuard(mutex); + if (!isOn) { + clipPlugin_ = nullptr; + return; + } + if (clipPlugin_ != nullptr) { + return; + } + auto release = [this](ClipPlugin *plugin) { + std::lock_guard lockGuard(mutex); + ClipPlugin::DestroyPlugin(PLUGIN_NAME, plugin); + }; + + clipPlugin_ = std::shared_ptr(ClipPlugin::CreatePlugin(PLUGIN_NAME), release); +} + +bool PasteboardService::GetDistributedEvent(std::shared_ptr plugin, int32_t user, Event &event) +{ + auto events = plugin->GetTopEvents(1, user); + if (events.empty()) { + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "events empty."); + return false; + } + + auto &tmpEvent = events[0]; + if (tmpEvent.deviceId == DMAdapter::GetInstance().GetLocalNetworkId()) { + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "get local data."); + return false; + } + if (tmpEvent.account != AccountManager::GetInstance().GetCurrentAccount()) { + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "account error."); + return false; + } + if (tmpEvent.deviceId == currentEvent_.deviceId && tmpEvent.seqId == currentEvent_.seqId) { + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "get same remote data."); + return false; + } + + event = std::move(tmpEvent); + uint64_t curTime = + static_cast(duration_cast(system_clock::now().time_since_epoch()).count()); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "result compare time = %{public}d", curTime < event.expiration); + return ((curTime < event.expiration) && (event.status == ClipPlugin::EVT_NORMAL)); +} + +std::string PasteboardService::GetAppLabel(uint32_t tokenId) +{ + auto iBundleMgr = GetAppBundleManager(); + if (iBundleMgr == nullptr) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, " Failed to cast bundle mgr service."); + return PasteBoardDialog::DEFAULT_LABEL; + } + AppInfo info = GetAppInfo(tokenId); + AppExecFwk::ApplicationInfo appInfo; + auto result = iBundleMgr->GetApplicationInfo(info.bundleName, 0, info.userId, appInfo); + if (!result) { + return PasteBoardDialog::DEFAULT_LABEL; + } + auto &resource = appInfo.labelResource; + auto label = iBundleMgr->GetStringById(resource.bundleName, resource.moduleName, resource.id, info.userId); + return label.empty() ? PasteBoardDialog::DEFAULT_LABEL : label; +} + +sptr PasteboardService::GetAppBundleManager() +{ + auto systemAbilityManager = OHOS::SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (systemAbilityManager == nullptr) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, " Failed to get SystemAbilityManager."); + return nullptr; + } + auto remoteObject = systemAbilityManager->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID); + if (remoteObject == nullptr) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, " Failed to get bundle mgr service."); + return nullptr; + } + return OHOS::iface_cast(remoteObject); +} + +void PasteBoardCommonEventSubscriber::OnReceiveEvent(const EventFwk::CommonEventData &data) +{ + auto want = data.GetWant(); + std::string action = want.GetAction(); + if (action == EventFwk::CommonEventSupport::COMMON_EVENT_USER_SWITCHED) { + std::lock_guard lock(mutex_); + int32_t userId = data.GetCode(); + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "user id switched: %{public}d", userId); + PasteboardService::currentUserId = userId; + } +} +} // namespace MiscServices +} // namespace OHOS \ No newline at end of file diff --git a/pasteboard/services/dfx/src/behaviour/behaviour_reporter.h b/pasteboard/services/dfx/src/behaviour/behaviour_reporter.h new file mode 100644 index 00000000..c3d3f150 --- /dev/null +++ b/pasteboard/services/dfx/src/behaviour/behaviour_reporter.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MISCSERVICES_PASTEBOARD_BEHAVIOUR_REPORTER_H +#define MISCSERVICES_PASTEBOARD_BEHAVIOUR_REPORTER_H + +#include "dfx_types.h" + +namespace OHOS { +namespace MiscServices { +class BehaviourReporter { +public: + virtual ReportStatus Report(const PasteboardBehaviourMsg &msg) = 0; + virtual ~BehaviourReporter() + { + } +}; +} // namespace MiscServices +} // namespace OHOS +#endif // MISCSERVICES_PASTEBOARD_BEHAVIOUR_REPORTER_H diff --git a/pasteboard/services/dfx/src/behaviour/pasteboard_behaviour_reporter_impl.cpp b/pasteboard/services/dfx/src/behaviour/pasteboard_behaviour_reporter_impl.cpp new file mode 100644 index 00000000..5ff00a67 --- /dev/null +++ b/pasteboard/services/dfx/src/behaviour/pasteboard_behaviour_reporter_impl.cpp @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "pasteboard_behaviour_reporter_impl.h" + +#include "dfx_code_constant.h" +#include "hiview_adapter.h" + +namespace OHOS { +namespace MiscServices { +ReportStatus PasteboardBehaviourReporterImpl::Report(const PasteboardBehaviourMsg &msg) +{ + HiViewAdapter::ReportPasteboardBehaviour(msg); + return ReportStatus::SUCCESS; +} +} // namespace MiscServices +} // namespace OHOS diff --git a/pasteboard/services/dfx/src/behaviour/pasteboard_behaviour_reporter_impl.h b/pasteboard/services/dfx/src/behaviour/pasteboard_behaviour_reporter_impl.h new file mode 100644 index 00000000..4fd4f9a5 --- /dev/null +++ b/pasteboard/services/dfx/src/behaviour/pasteboard_behaviour_reporter_impl.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MISCSERVICES_PASTEBOARD_BEHAVIOUR_REPORTER_IMPL_H +#define MISCSERVICES_PASTEBOARD_BEHAVIOUR_REPORTER_IMPL_H + +#include "behaviour_reporter.h" +#include "dfx_types.h" + +namespace OHOS { +namespace MiscServices { +class PasteboardBehaviourReporterImpl : public BehaviourReporter { +public: + ReportStatus Report(const struct PasteboardBehaviourMsg &msg) override; +}; +} // namespace MiscServices +} // namespace OHOS +#endif // MISCSERVICES_PASTEBOARD_BEHAVIOUR_REPORTER_IMPL_H diff --git a/pasteboard/services/dfx/src/calculate_time_consuming.cpp b/pasteboard/services/dfx/src/calculate_time_consuming.cpp new file mode 100644 index 00000000..b4d77b5d --- /dev/null +++ b/pasteboard/services/dfx/src/calculate_time_consuming.cpp @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "calculate_time_consuming.h" + +#include + +#include "dfx_types.h" +#include "pasteboard_hilog.h" +#include "reporter.h" +#include "statistic_reporter.h" + +namespace OHOS { +namespace MiscServices { +uint64_t CalculateTimeConsuming::lastTime_ = 0; +void CalculateTimeConsuming::SetBeginTime() +{ + lastTime_ = GetCurrentTimeMicros(); +} +CalculateTimeConsuming::CalculateTimeConsuming(const size_t calPasteboardData, const int calPasteboardState) + : pasteboardState_(calPasteboardState) +{ + pasteboardData_ = CalculateData(calPasteboardData); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "CalculateTimeConsuming()"); +} + +CalculateTimeConsuming::~CalculateTimeConsuming() +{ + uint64_t delta = GetCurrentTimeMicros() - lastTime_; + int calculateTime = CalculateTime(delta); + Reporter::GetInstance().TimeConsumingStatistic().Report({ pasteboardState_, pasteboardData_, calculateTime }); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "~CalculateTimeConsuming()"); +} + +int CalculateTimeConsuming::CalculateData(size_t calPasteboardData) const +{ + constexpr int M_BTYE = 1024; + constexpr int TC_ZERO_KB = 0; + constexpr int TC_HUNDRED_KB = 100; + constexpr int TC_FIVE_HUNDRED = 500; + constexpr int TC_ONE_MB = 1; + constexpr int TC_FIVE_MB = 5; + constexpr int TC_TEN_MB = 10; + constexpr int TC_FIFTY_MB = 50; + + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "CalculateData() enter"); + if (calPasteboardData % M_BTYE == 0) { + if (calPasteboardData >= TC_ZERO_KB && calPasteboardData < TC_HUNDRED_KB) { + return static_cast(DataRange::DR_ZERO_TO_HUNDRED_KB); + } else if (calPasteboardData >= TC_HUNDRED_KB && calPasteboardData < TC_FIVE_HUNDRED) { + return static_cast(DataRange::DR_HUNDRED_TO_FIVE_HUNDREDS_KB); + } else { + return static_cast(DataRange::DR_FIVE_HUNDREDS_TO_THOUSAND_KB); + } + } else { + size_t dataSize = calPasteboardData % M_BTYE; + if (dataSize >= TC_ONE_MB && dataSize < TC_FIVE_MB) { + return static_cast(DataRange::DR_ONE_TO_FIVE_MB); + } else if (dataSize >= TC_FIVE_MB && dataSize < TC_TEN_MB) { + return static_cast(DataRange::DR_FIVE_TO_TEN_MB); + } else if (dataSize >= TC_TEN_MB && dataSize < TC_FIFTY_MB) { + return static_cast(DataRange::DR_TEN_TO_FIFTY_MB); + } else { + return static_cast(DataRange::DR_OVER_FIFTY_MB); + } + } + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "CalculateData() end"); +} + +int CalculateTimeConsuming::CalculateTime(uint64_t time) +{ + constexpr int FIVE_HUNDRED_MS = 500; + uint64_t timeCosuming = time % FIVE_HUNDRED_MS; + switch (timeCosuming) { + case static_cast(TimeLevel::PER_FIVE_HUNDRED_MS_ZERO): + return static_cast(TimeConsumingStatistic::TCS_TIME_CONSUMING_LEVEL_ONE); + case static_cast(TimeLevel::PER_FIVE_HUNDRED_MS_ONE): + return static_cast(TimeConsumingStatistic::TCS_TIME_CONSUMING_LEVEL_TWO); + case static_cast(TimeLevel::PER_FIVE_HUNDRED_MS_TWO): + return static_cast(TimeConsumingStatistic::TCS_TIME_CONSUMING_LEVEL_THREE); + case static_cast(TimeLevel::PER_FIVE_HUNDRED_MS_THREE): + return static_cast(TimeConsumingStatistic::TCS_TIME_CONSUMING_LEVEL_FOUR); + case static_cast(TimeLevel::PER_FIVE_HUNDRED_MS_FOUR): + return static_cast(TimeConsumingStatistic::TCS_TIME_CONSUMING_LEVEL_FIVE); + case static_cast(TimeLevel::PER_FIVE_HUNDRED_MS_FIVE): + return static_cast(TimeConsumingStatistic::TCS_TIME_CONSUMING_LEVEL_SIX); + case static_cast(TimeLevel::PER_FIVE_HUNDRED_MS_SIX): + return static_cast(TimeConsumingStatistic::TCS_TIME_CONSUMING_LEVEL_SEVEN); + case static_cast(TimeLevel::PER_FIVE_HUNDRED_MS_SEVEN): + return static_cast(TimeConsumingStatistic::TCS_TIME_CONSUMING_LEVEL_EIGHT); + case static_cast(TimeLevel::PER_FIVE_HUNDRED_MS_EIGHT): + return static_cast(TimeConsumingStatistic::TCS_TIME_CONSUMING_LEVEL_NINE); + case static_cast(TimeLevel::PER_FIVE_HUNDRED_MS_NINE): + return static_cast(TimeConsumingStatistic::TCS_TIME_CONSUMING_LEVEL_TEN); + default: + return static_cast(TimeConsumingStatistic::TCS_TIME_CONSUMING_LEVEL_ELEVEN); + } +} + +uint64_t CalculateTimeConsuming::GetCurrentTimeMicros() +{ + constexpr int64_t SEC_TO_MILLISEC = 1000; + constexpr int64_t MICROSEC_TO_MILLISEC = 1000; + + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "GetCurrentTimeMicros() start"); + struct timeval tv = { 0, 0 }; + gettimeofday(&tv, nullptr); + return (tv.tv_sec * SEC_TO_MILLISEC + tv.tv_usec / MICROSEC_TO_MILLISEC); +} +} // namespace MiscServices +} // namespace OHOS diff --git a/pasteboard/services/dfx/src/calculate_time_consuming.h b/pasteboard/services/dfx/src/calculate_time_consuming.h new file mode 100644 index 00000000..723e8859 --- /dev/null +++ b/pasteboard/services/dfx/src/calculate_time_consuming.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef TIME_CONSUMING_H +#define TIME_CONSUMING_H + +#include +#include + +#include "singleton.h" + +namespace OHOS { +namespace MiscServices { +enum class TimeLevel : std::uint64_t { + PER_FIVE_HUNDRED_MS_ZERO = 0, + PER_FIVE_HUNDRED_MS_ONE, + PER_FIVE_HUNDRED_MS_TWO, + PER_FIVE_HUNDRED_MS_THREE, + PER_FIVE_HUNDRED_MS_FOUR, + PER_FIVE_HUNDRED_MS_FIVE, + PER_FIVE_HUNDRED_MS_SIX, + PER_FIVE_HUNDRED_MS_SEVEN, + PER_FIVE_HUNDRED_MS_EIGHT, + PER_FIVE_HUNDRED_MS_NINE, +}; + +class CalculateTimeConsuming : public Singleton { +public: + CalculateTimeConsuming(const size_t calPasteboardData, const int calPasteboardState); + ~CalculateTimeConsuming(); + static void SetBeginTime(); + +private: + static uint64_t GetCurrentTimeMicros(); + int CalculateTime(uint64_t time); + int CalculateData(size_t calPasteboardData) const; + + int pasteboardData_; + int pasteboardState_; + static uint64_t lastTime_; +}; +} // namespace MiscServices +} // namespace OHOS +#endif // TIME_CONSUMING_H diff --git a/pasteboard/services/dfx/src/command.cpp b/pasteboard/services/dfx/src/command.cpp new file mode 100644 index 00000000..f74ec0dc --- /dev/null +++ b/pasteboard/services/dfx/src/command.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "command.h" + +namespace OHOS { +namespace MiscServices { +Command::Command(const std::vector &argsFormat, const std::string &help, const Command::Action &action) + : format_(argsFormat), help_(help), action_(action) +{ +} + +Command::Command(const std::vector &argsFormat, const std::string &help) + : format_(argsFormat), help_(help) +{ +} + +std::string Command::ShowHelp() +{ + return help_; +} + +bool Command::DoAction(const std::vector &input, std::string &output) +{ + return action_(input, output); +} + +std::string Command::GetOption() +{ + return format_.at(0); +} + +std::string Command::GetFormat() +{ + std::string formatStr; + for (auto &seg : format_) { + formatStr += seg; + formatStr += " "; + } + return formatStr; +} +} // namespace MiscServices +} // namespace OHOS \ No newline at end of file diff --git a/pasteboard/services/dfx/src/command.h b/pasteboard/services/dfx/src/command.h new file mode 100644 index 00000000..61b5c343 --- /dev/null +++ b/pasteboard/services/dfx/src/command.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MISCSERVICES_PASTEBOARD_COMMAND_H +#define MISCSERVICES_PASTEBOARD_COMMAND_H + +#include +#include +#include + +namespace OHOS { +namespace MiscServices { +class Command { +public: + using Action = std::function &input, std::string &output)>; + explicit Command() = default; + Command(const std::vector &argsFormat, const std::string &help, const Action &action); + Command(const std::vector &argsFormat, const std::string &help); + virtual ~Command() = default; + virtual std::string ShowHelp(); + virtual bool DoAction(const std::vector &input, std::string &output); + virtual std::string GetOption(); + virtual std::string GetFormat(); + +private: + std::vector format_; + std::string help_; + Action action_; +}; +} // namespace MiscServices +} // namespace OHOS +#endif // MISCSERVICES_PASTEBOARD_COMMAND_H diff --git a/pasteboard/services/dfx/src/dfx_code_constant.h b/pasteboard/services/dfx/src/dfx_code_constant.h new file mode 100644 index 00000000..6705170c --- /dev/null +++ b/pasteboard/services/dfx/src/dfx_code_constant.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MISCSERVICES_PASTEBOARD_DFX_CODE_CONSTANT_H +#define MISCSERVICES_PASTEBOARD_DFX_CODE_CONSTANT_H + +class DfxCodeConstant { +public: + static inline constexpr int PASTEBOARD_FAULT = 950001100; + static inline constexpr int TIME_CONSUMING_STATISTIC = 950001105; + static inline constexpr int PASTEBOARD_BEHAVIOUR = 950001106; + static inline constexpr int USE_BEHAVIOUR = 950001107; +}; +#endif // MISCSERVICES_PASTEBOARD_DFX_CODE_CONSTANT_H diff --git a/pasteboard/services/dfx/src/dfx_types.h b/pasteboard/services/dfx/src/dfx_types.h new file mode 100644 index 00000000..80d6ed08 --- /dev/null +++ b/pasteboard/services/dfx/src/dfx_types.h @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MISCSERVICES_PASTEBOARD_DFX_TYPES_H +#define MISCSERVICES_PASTEBOARD_DFX_TYPES_H + +#include +#include +#include + +namespace OHOS { +namespace MiscServices { +enum TimeConsumingStatistic : std::int32_t { + TCS_TIME_CONSUMING_LEVEL_ONE = 0, + TCS_TIME_CONSUMING_LEVEL_TWO, + TCS_TIME_CONSUMING_LEVEL_THREE, + TCS_TIME_CONSUMING_LEVEL_FOUR, + TCS_TIME_CONSUMING_LEVEL_FIVE, + TCS_TIME_CONSUMING_LEVEL_SIX, + TCS_TIME_CONSUMING_LEVEL_SEVEN, + TCS_TIME_CONSUMING_LEVEL_EIGHT, + TCS_TIME_CONSUMING_LEVEL_NINE, + TCS_TIME_CONSUMING_LEVEL_TEN, + TCS_TIME_CONSUMING_LEVEL_ELEVEN, +}; + +enum BehaviourPasteboardState : std::int32_t { + BPS_COPY_STATE = 0, + BPS_PASTE_STATE, + BPS_REMOTE_PASTE_STATE, + BPS_INVALID_STATE, +}; + +enum StatisticPasteboardState : std::int32_t { + SPS_COPY_STATE = 0, + SPS_PASTE_STATE, + SPS_REMOTE_PASTE_STATE, + SPS_INVALID_STATE, +}; + +enum DataRange : std::int32_t { + DR_ZERO_TO_HUNDRED_KB = 0, + DR_HUNDRED_TO_FIVE_HUNDREDS_KB, + DR_FIVE_HUNDREDS_TO_THOUSAND_KB, + DR_ONE_TO_FIVE_MB, + DR_FIVE_TO_TEN_MB, + DR_TEN_TO_FIFTY_MB, + DR_OVER_FIFTY_MB, +}; + +struct PasteboardFaultMsg { + int32_t userId; + std::string errorCode; +}; + +struct PasteboardBehaviourMsg { + int pasteboardState; + std::string bundleName; +}; + +struct TimeConsumingStat { + int pasteboardState; + int dataSize; + int timeConsuming; +}; + +enum class ReportStatus { + SUCCESS = 0, + ERROR = 1, +}; +} // namespace MiscServices +} // namespace OHOS +#endif // MISCSERVICES_PASTEBOARD_DFX_TYPES_H diff --git a/pasteboard/services/dfx/src/fault/fault_reporter.h b/pasteboard/services/dfx/src/fault/fault_reporter.h new file mode 100644 index 00000000..b4ad72d7 --- /dev/null +++ b/pasteboard/services/dfx/src/fault/fault_reporter.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MISCSERVICES_PASTEBOARD_FAULT_REPORTER_H +#define MISCSERVICES_PASTEBOARD_FAULT_REPORTER_H + +#include "dfx_types.h" + +namespace OHOS { +namespace MiscServices { +class FaultReporter { +public: + virtual ReportStatus Report(const PasteboardFaultMsg &msg) = 0; + virtual ~FaultReporter() + { + } +}; +} // namespace MiscServices +} // namespace OHOS +#endif // MISCSERVICES_PASTEBOARD_FAULT_REPORTER_H diff --git a/pasteboard/services/dfx/src/fault/pasteboard_fault_impl.cpp b/pasteboard/services/dfx/src/fault/pasteboard_fault_impl.cpp new file mode 100644 index 00000000..98cc921e --- /dev/null +++ b/pasteboard/services/dfx/src/fault/pasteboard_fault_impl.cpp @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "pasteboard_fault_impl.h" + +#include "dfx_code_constant.h" +#include "hiview_adapter.h" + +namespace OHOS { +namespace MiscServices { +ReportStatus PasteboardFaultImpl::Report(const PasteboardFaultMsg &msg) +{ + HiViewAdapter::ReportPasteboardFault(DfxCodeConstant::PASTEBOARD_FAULT, msg); + return ReportStatus::SUCCESS; +} +} // namespace MiscServices +} // namespace OHOS diff --git a/pasteboard/services/dfx/src/fault/pasteboard_fault_impl.h b/pasteboard/services/dfx/src/fault/pasteboard_fault_impl.h new file mode 100644 index 00000000..9fa62798 --- /dev/null +++ b/pasteboard/services/dfx/src/fault/pasteboard_fault_impl.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MISCSERVICES_PASTEBOARD_INITIALIZATION_FAULT_IMPL_H +#define MISCSERVICES_PASTEBOARD_INITIALIZATION_FAULT_IMPL_H + +#include "dfx_types.h" +#include "fault_reporter.h" + +namespace OHOS { +namespace MiscServices { +class PasteboardFaultImpl : public FaultReporter { +public: + ReportStatus Report(const PasteboardFaultMsg &msg) override; +}; +} // namespace MiscServices +} // namespace OHOS +#endif // MISCSERVICES_PASTEBOARD_INITIALIZATION_FAULT_IMPL_H diff --git a/pasteboard/services/dfx/src/hiview_adapter.cpp b/pasteboard/services/dfx/src/hiview_adapter.cpp new file mode 100644 index 00000000..62fddde9 --- /dev/null +++ b/pasteboard/services/dfx/src/hiview_adapter.cpp @@ -0,0 +1,523 @@ +/* + * Copyright (C) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "HiViewAdapter" + +#include "hiview_adapter.h" + +#include +#include +#include +#include + +#include "def.h" +#include "pasteboard_hilog.h" +#include "pasteboard_error.h" +#include "time_service_client.h" + +namespace OHOS { +using namespace HiviewDFX; +namespace MiscServices { +namespace { +const std::map EVENT_COVERT_TABLE = { + { DfxCodeConstant::PASTEBOARD_FAULT, "PASTEBOARD_FAULT" }, + { DfxCodeConstant::TIME_CONSUMING_STATISTIC, "TIME_CONSUMING_STATISTIC" }, + { DfxCodeConstant::PASTEBOARD_BEHAVIOUR, "PASTEBOARD_BEHAVIOUR" }, + { DfxCodeConstant::USE_BEHAVIOUR, "USE_BEHAVIOUR" }, +}; +} // namespace + +bool HiViewAdapter::running_ = false; +std::mutex HiViewAdapter::runMutex_; +std::mutex HiViewAdapter::timeConsumingMutex_; +std::mutex HiViewAdapter::behaviourMutex_; +std::vector> HiViewAdapter::copyTimeConsumingStat_; +std::vector> HiViewAdapter::pasteTimeConsumingStat_; +std::vector> HiViewAdapter::remotePasteTimeConsumingStat_; + +std::map HiViewAdapter::copyPasteboardBehaviour_; +std::map HiViewAdapter::pastePasteboardBehaviour_; +std::map HiViewAdapter::remotePastePasteboardBehaviour_; + +std::map HiViewAdapter::dataMap_ = HiViewAdapter::InitDataMap(); +std::map HiViewAdapter::timeMap_ = HiViewAdapter::InitTimeMap(); + +std::map HiViewAdapter::InitDataMap() +{ + std::map dataMap; + dataMap.insert(std::pair( + static_cast(DataRange::DR_ZERO_TO_HUNDRED_KB), static_cast(DataConsumingLevel::DATA_LEVEL_ONE))); + dataMap.insert(std::pair(static_cast(DataRange::DR_HUNDRED_TO_FIVE_HUNDREDS_KB), + static_cast(DataConsumingLevel::DATA_LEVEL_TWO))); + dataMap.insert(std::pair(static_cast(DataRange::DR_FIVE_HUNDREDS_TO_THOUSAND_KB), + static_cast(DataConsumingLevel::DATA_LEVEL_THREE))); + dataMap.insert(std::pair( + static_cast(DataRange::DR_ONE_TO_FIVE_MB), static_cast(DataConsumingLevel::DATA_LEVEL_FOUR))); + dataMap.insert(std::pair( + static_cast(DataRange::DR_FIVE_TO_TEN_MB), static_cast(DataConsumingLevel::DATA_LEVEL_FIVE))); + dataMap.insert(std::pair( + static_cast(DataRange::DR_TEN_TO_FIFTY_MB), static_cast(DataConsumingLevel::DATA_LEVEL_SIX))); + dataMap.insert(std::pair( + static_cast(DataRange::DR_OVER_FIFTY_MB), static_cast(DataConsumingLevel::DATA_LEVEL_SEVEN))); + return dataMap; +} + +std::map HiViewAdapter::InitTimeMap() +{ + std::map timeMap; + timeMap.insert(std::pair(static_cast(TimeConsumingStatistic::TCS_TIME_CONSUMING_LEVEL_ONE), + static_cast(TimeConsumingLevel::TIME_LEVEL_ONE))); + timeMap.insert(std::pair(static_cast(TimeConsumingStatistic::TCS_TIME_CONSUMING_LEVEL_TWO), + static_cast(TimeConsumingLevel::TIME_LEVEL_TWO))); + timeMap.insert(std::pair(static_cast(TimeConsumingStatistic::TCS_TIME_CONSUMING_LEVEL_THREE), + static_cast(TimeConsumingLevel::TIME_LEVEL_THREE))); + timeMap.insert(std::pair(static_cast(TimeConsumingStatistic::TCS_TIME_CONSUMING_LEVEL_FOUR), + static_cast(TimeConsumingLevel::TIME_LEVEL_FOUR))); + timeMap.insert(std::pair(static_cast(TimeConsumingStatistic::TCS_TIME_CONSUMING_LEVEL_FIVE), + static_cast(TimeConsumingLevel::TIME_LEVEL_FIVE))); + timeMap.insert(std::pair(static_cast(TimeConsumingStatistic::TCS_TIME_CONSUMING_LEVEL_SIX), + static_cast(TimeConsumingLevel::TIME_LEVEL_SIX))); + timeMap.insert(std::pair(static_cast(TimeConsumingStatistic::TCS_TIME_CONSUMING_LEVEL_SEVEN), + static_cast(TimeConsumingLevel::TIME_LEVEL_SEVEN))); + timeMap.insert(std::pair(static_cast(TimeConsumingStatistic::TCS_TIME_CONSUMING_LEVEL_EIGHT), + static_cast(TimeConsumingLevel::TIME_LEVEL_EIGHT))); + timeMap.insert(std::pair(static_cast(TimeConsumingStatistic::TCS_TIME_CONSUMING_LEVEL_NINE), + static_cast(TimeConsumingLevel::TIME_LEVEL_NINE))); + timeMap.insert(std::pair(static_cast(TimeConsumingStatistic::TCS_TIME_CONSUMING_LEVEL_TEN), + static_cast(TimeConsumingLevel::TIME_LEVEL_TEN))); + timeMap.insert(std::pair(static_cast(TimeConsumingStatistic::TCS_TIME_CONSUMING_LEVEL_ELEVEN), + static_cast(TimeConsumingLevel::TIME_LEVEL_ELEVEN))); + return timeMap; +} + +void HiViewAdapter::ReportPasteboardFault(int dfxCode, const PasteboardFaultMsg &msg) +{ + constexpr const char *USER_ID = "USER_ID"; + constexpr const char *ERROR_TYPE = "ERROR_TYPE"; + int ret = HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::PASTEBOARD, CoverEventID(dfxCode), + HiSysEvent::EventType::FAULT, USER_ID, msg.userId, ERROR_TYPE, msg.errorCode); + if (ret != 0) { + PASTEBOARD_HILOGD( + PASTEBOARD_MODULE_SERVICE, "hisysevent write failed! ret %{public}d. errCode %{public}d", ret, dfxCode); + } +} + +void HiViewAdapter::InitializeTimeConsuming(int initFlag) +{ + constexpr const int DATA_LEVEL_NUMBERS = 7; + std::map initTimeConsuming; + initTimeConsuming.insert(std::pair(static_cast(TimeConsumingLevel::TIME_LEVEL_ONE), 0)); + initTimeConsuming.insert(std::pair(static_cast(TimeConsumingLevel::TIME_LEVEL_TWO), 0)); + initTimeConsuming.insert(std::pair(static_cast(TimeConsumingLevel::TIME_LEVEL_THREE), 0)); + initTimeConsuming.insert(std::pair(static_cast(TimeConsumingLevel::TIME_LEVEL_FOUR), 0)); + initTimeConsuming.insert(std::pair(static_cast(TimeConsumingLevel::TIME_LEVEL_FIVE), 0)); + initTimeConsuming.insert(std::pair(static_cast(TimeConsumingLevel::TIME_LEVEL_SIX), 0)); + initTimeConsuming.insert(std::pair(static_cast(TimeConsumingLevel::TIME_LEVEL_SEVEN), 0)); + initTimeConsuming.insert(std::pair(static_cast(TimeConsumingLevel::TIME_LEVEL_EIGHT), 0)); + initTimeConsuming.insert(std::pair(static_cast(TimeConsumingLevel::TIME_LEVEL_NINE), 0)); + initTimeConsuming.insert(std::pair(static_cast(TimeConsumingLevel::TIME_LEVEL_TEN), 0)); + initTimeConsuming.insert(std::pair(static_cast(TimeConsumingLevel::TIME_LEVEL_ELEVEN), 0)); + + if (initFlag == INIT_COPY_TIME_SONSUMING) { + for (int i = 0; i < DATA_LEVEL_NUMBERS; ++i) { + copyTimeConsumingStat_.push_back(initTimeConsuming); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "copyTimeConsumingStat_.push_back"); + } + } else if (initFlag == INIT_PASTE_TIME_SONSUMING) { + for (int i = 0; i < DATA_LEVEL_NUMBERS; ++i) { + pasteTimeConsumingStat_.push_back(initTimeConsuming); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "pasteTimeConsumingStat_.push_back"); + } + } else { + for (int i = 0; i < DATA_LEVEL_NUMBERS; ++i) { + remotePasteTimeConsumingStat_.push_back(initTimeConsuming); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "remotePasteTimeConsumingStat_.push_back"); + } + } +} + +void HiViewAdapter::ReportTimeConsumingStatistic(const TimeConsumingStat &stat) +{ + std::lock_guard lock(timeConsumingMutex_); + if (copyTimeConsumingStat_.empty()) { + InitializeTimeConsuming(INIT_COPY_TIME_SONSUMING); + } + if (pasteTimeConsumingStat_.empty()) { + InitializeTimeConsuming(INIT_PASTE_TIME_SONSUMING); + } + if (remotePasteTimeConsumingStat_.empty()) { + InitializeTimeConsuming(INIT_REMOTE_PASTE_TIME_SONSUMING); + } + + if (stat.pasteboardState == static_cast(StatisticPasteboardState::SPS_COPY_STATE)) { + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "hisysevent pasteboard state is %{public}d", stat.pasteboardState); + auto iter = dataMap_.find(stat.dataSize); + if (iter != dataMap_.end()) { + CopyTimeConsuming(stat, iter->second); + } else { + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "wrong data level"); + } + } else if ((stat.pasteboardState == static_cast(StatisticPasteboardState::SPS_PASTE_STATE)) || + (stat.pasteboardState == static_cast(StatisticPasteboardState::SPS_REMOTE_PASTE_STATE))) { + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "hisysevent pasteboard state is %{public}d", stat.pasteboardState); + auto iter = dataMap_.find(stat.dataSize); + if (iter != dataMap_.end()) { + PasteTimeConsuming(stat, iter->second); + } else { + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "wrong data level"); + } + } else { + PASTEBOARD_HILOGD( + PASTEBOARD_MODULE_SERVICE, "hisysevent wrong pasteboard state! errCode %{public}d", stat.pasteboardState); + } +} + +void HiViewAdapter::CopyTimeConsumingCount(int dataLevel, int timeLevel) +{ + if (static_cast(copyTimeConsumingStat_.size()) <= dataLevel) { + return; + } + auto it = copyTimeConsumingStat_[dataLevel].find(timeLevel); + if (it != copyTimeConsumingStat_[dataLevel].end()) { + (it->second)++; + } else { + PASTEBOARD_HILOGD( + PASTEBOARD_MODULE_SERVICE, "hisysevent wrong copy time level, tiem level: %{public}d", timeLevel); + } +} + +void HiViewAdapter::PasteTimeConsumingCount(int dataLevel, int timeLevel) +{ + if (static_cast(pasteTimeConsumingStat_.size()) <= dataLevel) { + return; + } + auto it = pasteTimeConsumingStat_[dataLevel].find(timeLevel); + if (it != pasteTimeConsumingStat_[dataLevel].end()) { + (it->second)++; + } else { + PASTEBOARD_HILOGD( + PASTEBOARD_MODULE_SERVICE, "hisysevent wrong copy time level, tiem level: %{public}d", timeLevel); + } +} + +void HiViewAdapter::RemotePasteTimeConsumingCount(int dataLevel, int timeLevel) +{ + if (static_cast(remotePasteTimeConsumingStat_.size()) <= dataLevel) { + return; + } + auto it = remotePasteTimeConsumingStat_[dataLevel].find(timeLevel); + if (it != remotePasteTimeConsumingStat_[dataLevel].end()) { + (it->second)++; + } else { + PASTEBOARD_HILOGD( + PASTEBOARD_MODULE_SERVICE, "hisysevent wrong copy time level, tiem level: %{public}d", timeLevel); + } +} + +void HiViewAdapter::CopyTimeConsuming(const TimeConsumingStat &stat, int level) +{ + auto iter = timeMap_.find(stat.timeConsuming); + if (iter != timeMap_.end()) { + CopyTimeConsumingCount(level, iter->second); + } else { + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "wrong time level"); + } +} + +void HiViewAdapter::PasteTimeConsuming(const TimeConsumingStat &stat, int level) +{ + auto iter = timeMap_.find(stat.timeConsuming); + if (iter != timeMap_.end()) { + if (stat.pasteboardState == SPS_PASTE_STATE) { + PasteTimeConsumingCount(level, iter->second); + } else { + RemotePasteTimeConsumingCount(level, iter->second); + } + } else { + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "wrong time level"); + } +} + +void HiViewAdapter::ReportPasteboardBehaviour(const PasteboardBehaviourMsg &msg) +{ + std::lock_guard lock(behaviourMutex_); + + if (msg.pasteboardState == static_cast(BehaviourPasteboardState::BPS_COPY_STATE)) { + auto it = copyPasteboardBehaviour_.find(msg.bundleName); + if (it != copyPasteboardBehaviour_.end()) { + (it->second)++; + } else { + copyPasteboardBehaviour_.insert(std::pair(msg.bundleName, 1)); + } + } else if (msg.pasteboardState == static_cast(BehaviourPasteboardState::BPS_PASTE_STATE)) { + auto it = pastePasteboardBehaviour_.find(msg.bundleName); + if (it != pastePasteboardBehaviour_.end()) { + (it->second)++; + } else { + pastePasteboardBehaviour_.insert(std::pair(msg.bundleName, 1)); + } + } else if (msg.pasteboardState == static_cast(BehaviourPasteboardState::BPS_REMOTE_PASTE_STATE)) { + auto it = remotePastePasteboardBehaviour_.find(msg.bundleName); + if (it != remotePastePasteboardBehaviour_.end()) { + (it->second)++; + } else { + remotePastePasteboardBehaviour_.insert(std::pair(msg.bundleName, 1)); + } + } else { + PASTEBOARD_HILOGD( + PASTEBOARD_MODULE_SERVICE, "hisysevent wrong pasteboard state! errCode %{public}d", msg.pasteboardState); + } +} + +const char *HiViewAdapter::GetDataLevel(int dataLevel) +{ + constexpr const char *WRONG_LEVEL = "WRONG_LEVEL"; + switch (dataLevel) { + case static_cast(DataConsumingLevel::DATA_LEVEL_ONE): { + return ZERO_TO_HUNDRED_KB; + } + case static_cast(DataConsumingLevel::DATA_LEVEL_TWO): { + return HUNDRED_TO_FIVE_HUNDREDS_KB; + } + case static_cast(DataConsumingLevel::DATA_LEVEL_THREE): { + return FIVE_HUNDREDS_TO_THOUSAND_KB; + } + case static_cast(DataConsumingLevel::DATA_LEVEL_FOUR): { + return ONE_TO_FIVE_MB; + } + case static_cast(DataConsumingLevel::DATA_LEVEL_FIVE): { + return FIVE_TO_TEN_MB; + } + case static_cast(DataConsumingLevel::DATA_LEVEL_SIX): { + return TEN_TO_FIFTY_MB; + } + case static_cast(DataConsumingLevel::DATA_LEVEL_SEVEN): { + return OVER_FIFTY_MB; + } + default: { + return WRONG_LEVEL; + } + } +} + +void HiViewAdapter::InvokeTimeConsuming() +{ + std::lock_guard lock(timeConsumingMutex_); + ReportStatisticEvent(copyTimeConsumingStat_, COPY_STATE); + copyTimeConsumingStat_.clear(); + ReportStatisticEvent(pasteTimeConsumingStat_, PASTE_STATE); + pasteTimeConsumingStat_.clear(); + ReportStatisticEvent(remotePasteTimeConsumingStat_, REMOTE_PASTE_STATE); + remotePasteTimeConsumingStat_.clear(); +} + +void HiViewAdapter::ReportStatisticEvent( + const std::vector> &timeConsumingStat, const std::string &pasteboardState) +{ + if (timeConsumingStat.empty()) { + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "hisysevent timeConsumingStat is empty."); + return; + } + for (std::int32_t i = 0; i < static_cast(timeConsumingStat.size()); ++i) { + std::string buffMsg = ": ["; + for (std::int32_t j = TimeConsumingLevel::TIME_LEVEL_ONE; j <= TimeConsumingLevel::TIME_LEVEL_ELEVEN; ++j) { + buffMsg = buffMsg + std::to_string(timeConsumingStat[i].at(j)) + ","; + } + buffMsg += "]"; + + int ret = -1; + if (pasteboardState == REMOTE_PASTE_STATE) { + std::string netType = "WIFI"; + ret = HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::PASTEBOARD, + CoverEventID(DfxCodeConstant::TIME_CONSUMING_STATISTIC), + HiSysEvent::EventType::STATISTIC, PASTEBOARD_STATE, pasteboardState, NET_TYPE, netType, DATA_LEVEL, + GetDataLevel(i), CONSUMING_DATA, buffMsg); + } else { + ret = HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::PASTEBOARD, + CoverEventID(DfxCodeConstant::TIME_CONSUMING_STATISTIC), + HiSysEvent::EventType::STATISTIC, PASTEBOARD_STATE, pasteboardState, DATA_LEVEL, GetDataLevel(i), + CONSUMING_DATA, buffMsg); + } + + if (ret != HiviewDFX::SUCCESS) { + PASTEBOARD_HILOGD( + PASTEBOARD_MODULE_SERVICE, "hisysevent write failed! ret = %{public}d, i = %{public}d.", ret, i); + } + } +} + +void HiViewAdapter::ReportBehaviour(std::map &behaviour, const char *pasteboardState) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "ReportBehaviour enter"); + if (!behaviour.empty()) { + std::vector> vec; + constexpr const int TOTAL_APP_NUMBERS = 10; + + for (auto it = behaviour.begin(); it != behaviour.end(); ++it) { + vec.push_back(std::pair(it->first, it->second)); + } + // sort + sort(vec.begin(), vec.end(), + [](std::pair a, std::pair b) { return a.second > b.second; }); + + std::vector appPackName; + for (int i = 0; i < TOTAL_APP_NUMBERS; ++i) { + appPackName.push_back("default"); + } + + int index = 0; + for (auto iter = vec.begin(); iter != vec.end(); ++iter) { + appPackName[index] = iter->first + " :" + std::to_string(iter->second); + ++index; + } + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "ReportBehaviour report "); + int ret = HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::PASTEBOARD, + CoverEventID(DfxCodeConstant::PASTEBOARD_BEHAVIOUR), + HiSysEvent::EventType::BEHAVIOR, PASTEBOARD_STATE, pasteboardState, TOP_ONE_APP, appPackName[0], + TOP_TOW_APP, appPackName[1], TOP_THREE_APP, appPackName[2], TOP_FOUR_APP, appPackName[3], TOP_FIVE_APP, + appPackName[4], TOP_SIX_APP, appPackName[5], TOP_SEVEN_APP, appPackName[6], TOP_EIGHT_APP, appPackName[7], + TOP_NINE_APP, appPackName[8], TOP_TEN_APP, appPackName[9]); + if (ret != HiviewDFX::SUCCESS) { + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "hisysevent write failed! ret %{public}d.", ret); + } + } else { + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "behaviour is empty!"); + } + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "ReportBehaviour end"); +} + +void HiViewAdapter::InvokePasteBoardBehaviour() +{ + std::lock_guard lock(behaviourMutex_); + if (!copyPasteboardBehaviour_.empty()) { + ReportBehaviour(copyPasteboardBehaviour_, COPY_STATE); + copyPasteboardBehaviour_.clear(); + } else { + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "InvokePasteBoardBehaviour :copyPasteboardBehaviour_ is empty "); + } + if (!pastePasteboardBehaviour_.empty()) { + ReportBehaviour(pastePasteboardBehaviour_, PASTE_STATE); + pastePasteboardBehaviour_.clear(); + } else { + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "InvokePasteBoardBehaviour :pastePasteboardBehaviour_ is empty "); + } + if (!remotePastePasteboardBehaviour_.empty()) { + ReportBehaviour(remotePastePasteboardBehaviour_, REMOTE_PASTE_STATE); + remotePastePasteboardBehaviour_.clear(); + } else { + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "remotePastePasteboardBehaviour_ is empty "); + } +} + +void HiViewAdapter::StartTimerThread() +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "StartTimerThread enter"); + std::lock_guard lock(runMutex_); + if (running_) { + return; + } + running_ = true; + auto fun = []() { + while (true) { + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "StartTimerThread while"); + time_t current = time(nullptr); + if (current == -1) { + sleep(ONE_HOUR_IN_SECONDS); + continue; + } + + tm localTime = { 0 }; + tm *result = localtime_r(¤t, &localTime); + if (result == nullptr) { + sleep(ONE_HOUR_IN_SECONDS); + continue; + } + int currentHour = localTime.tm_hour; + int currentMin = localTime.tm_min; + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "StartTimerThread get"); + if ((EXEC_MIN_TIME - currentMin) != EXEC_MIN_TIME) { + int nHours = EXEC_HOUR_TIME - currentHour; + int nMin = EXEC_MIN_TIME - currentMin; + int nTime = (nMin)*ONE_MINUTE_IN_SECONDS + (nHours)*ONE_HOUR_IN_SECONDS; + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, + " StartTimerThread if needHours=%{public}d,needMin=%{public}d,needTime=%{public}d", nHours, nMin, + nTime); + sleep(nTime); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "StartTimerThread invoke"); + InvokePasteBoardBehaviour(); + InvokeTimeConsuming(); + } else { + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "StartTimerThread sleep"); + sleep(ONE_HOUR_IN_SECONDS * (ONE_DAY_IN_HOURS - currentHour)); + current = time(nullptr); + InvokePasteBoardBehaviour(); + InvokeTimeConsuming(); + } + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "StartTimerThread end"); + } + }; + std::thread th = std::thread(fun); + pthread_setname_np(th.native_handle(), "HiViewReport"); + th.detach(); +} + +void HiViewAdapter::ReportUseBehaviour(PasteData& pastData, const char* state, int32_t result) +{ + std::string bundleName = pastData.GetBundleName(); + std::string primaryMimeType = pastData.GetPrimaryMimeType() != nullptr? *pastData.GetPrimaryMimeType() : "null"; + std::string shareOption; + PasteData::ShareOptionToString(pastData.GetShareOption(), shareOption); + auto isLocalPaste = pastData.IsLocalPaste(); + auto isRemote = pastData.IsRemote(); + std::thread thread([bundleName, primaryMimeType, shareOption, isLocalPaste, isRemote, state, result]() { + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "start."); + auto iter = PasteboardErrorMap.find(PasteboardError(result)); + const char *appRet; + if (iter != PasteboardErrorMap.end()) { + appRet = iter->second; + } else { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "Match error result: %{public}d.", result); + appRet = "MATCH ERROR"; + } + int ret = HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::PASTEBOARD, + CoverEventID(DfxCodeConstant::USE_BEHAVIOUR), + HiSysEvent::EventType::BEHAVIOR, PASTEBOARD_STATE, state, + BOOTTIME, TimeServiceClient::GetInstance()->GetBootTimeMs(), + WALLTIME, TimeServiceClient::GetInstance()->GetWallTimeMs(), + RESULT, appRet, + OPERATE_APP, bundleName, + PRI_MIME_TYPE, primaryMimeType, + ISLOCALPASTE, isLocalPaste, + ISREMOTE, isRemote, + SHAREOPTION, shareOption); + if (ret != HiviewDFX::SUCCESS) { + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "hisysevent write failed! ret %{public}d.", ret); + } + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "end."); + }); + thread.detach(); +} + +std::string HiViewAdapter::CoverEventID(int dfxCode) +{ + std::string sysEventID = ""; + auto operatorIter = EVENT_COVERT_TABLE.find(dfxCode); + if (operatorIter != EVENT_COVERT_TABLE.end()) { + sysEventID = operatorIter->second; + } + return sysEventID; +} +} // namespace MiscServices +} // namespace OHOS diff --git a/pasteboard/services/dfx/src/hiview_adapter.h b/pasteboard/services/dfx/src/hiview_adapter.h new file mode 100644 index 00000000..482d8a26 --- /dev/null +++ b/pasteboard/services/dfx/src/hiview_adapter.h @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MISCSERVICES_PASTEBOARD_HI_VIEW_ADAPTER_H +#define MISCSERVICES_PASTEBOARD_HI_VIEW_ADAPTER_H + +#include +#include +#include +#include +#include + +#include "dfx_code_constant.h" +#include "dfx_types.h" +#include "hisysevent.h" +#include "paste_data.h" + +namespace OHOS { +namespace MiscServices { +enum DataConsumingLevel : std::int32_t { + DATA_LEVEL_ONE = 0, + DATA_LEVEL_TWO, + DATA_LEVEL_THREE, + DATA_LEVEL_FOUR, + DATA_LEVEL_FIVE, + DATA_LEVEL_SIX, + DATA_LEVEL_SEVEN, +}; +enum TimeConsumingLevel : std::int32_t { + TIME_LEVEL_ONE = 0, + TIME_LEVEL_TWO, + TIME_LEVEL_THREE, + TIME_LEVEL_FOUR, + TIME_LEVEL_FIVE, + TIME_LEVEL_SIX, + TIME_LEVEL_SEVEN, + TIME_LEVEL_EIGHT, + TIME_LEVEL_NINE, + TIME_LEVEL_TEN, + TIME_LEVEL_ELEVEN, +}; + +class HiViewAdapter { +public: + ~HiViewAdapter(); + + static inline const char *PASTEBOARD_STATE = "PASTEBOARD_STATE"; + static inline const char *COPY_STATE = "COPY_STATE"; + static inline const char *PASTE_STATE = "PASTE_STATE"; + + static void ReportPasteboardFault(int dfxCode, const PasteboardFaultMsg &msg); + static void ReportTimeConsumingStatistic(const TimeConsumingStat &stat); + static void ReportPasteboardBehaviour(const PasteboardBehaviourMsg &msg); + static void StartTimerThread(); + static std::map InitDataMap(); + static std::map InitTimeMap(); + + static void ReportUseBehaviour(PasteData& pastData, const char* state, int32_t result); + +private: + static void InvokePasteBoardBehaviour(); + static void InitializeTimeConsuming(int initFlag); + static void CopyTimeConsumingCount(int dataLevel, int timeLevel); + static void PasteTimeConsumingCount(int dataLevel, int timeLevel); + static void RemotePasteTimeConsumingCount(int dataLevel, int timeLevel); + static void CopyTimeConsuming(const TimeConsumingStat &stat, int level); + static void PasteTimeConsuming(const TimeConsumingStat &stat, int level); + static const char *GetDataLevel(int dataLevel); + static void InvokeTimeConsuming(); + static void ReportBehaviour(std::map &behaviour, const char *statePasteboard); + static void ReportStatisticEvent( + const std::vector> &timeConsumingStat, const std::string &pasteboardState); + + static std::mutex timeConsumingMutex_; + static std::vector> copyTimeConsumingStat_; + static std::vector> pasteTimeConsumingStat_; + static std::vector> remotePasteTimeConsumingStat_; + + static std::mutex behaviourMutex_; + static std::map copyPasteboardBehaviour_; + static std::map pastePasteboardBehaviour_; + static std::map remotePastePasteboardBehaviour_; + + static std::map dataMap_; + static std::map timeMap_; + + static std::string CoverEventID(int dfxCode); + +private: + static std::mutex runMutex_; + static bool running_; + + static inline constexpr int ONE_DAY_IN_HOURS = 24; + static inline constexpr int EXEC_HOUR_TIME = 23; + static inline constexpr int EXEC_MIN_TIME = 60; + static inline constexpr int ONE_MINUTE_IN_SECONDS = 60; + static inline constexpr int ONE_HOUR_IN_SECONDS = 1 * 60 * 60; // 1 hour + + // statistic key + static inline const char *ZERO_TO_HUNDRED_KB = "ZERO_TO_HUNDRED_KB"; + static inline const char *HUNDRED_TO_FIVE_HUNDREDS_KB = "HUNDRED_TO_FIVE_HUNDREDS_KB"; + static inline const char *FIVE_HUNDREDS_TO_THOUSAND_KB = "FIVE_HUNDREDS_TO_THOUSAND_KB"; + static inline const char *ONE_TO_FIVE_MB = "ONE_TO_FIVE_MB"; + static inline const char *FIVE_TO_TEN_MB = "FIVE_TO_TEN_MB"; + static inline const char *TEN_TO_FIFTY_MB = "TEN_TO_FIFTY_MB"; + static inline const char *OVER_FIFTY_MB = "OVER_FIFTY_MB"; + static inline const char *CONSUMING_DATA = "CONSUMING_DATA"; + static inline const char *DATA_LEVEL = "DATA_LEVEL"; + static inline constexpr const char *NET_TYPE = "NET_TYPE"; + // behaviour key + static inline const char *TOP_ONE_APP = "TOP_ONE_APP"; + static inline const char *TOP_TOW_APP = "TOP_TOW_APP"; + static inline const char *TOP_THREE_APP = "TOP_THREE_APP"; + static inline const char *TOP_FOUR_APP = "TOP_FOUR_APP"; + static inline const char *TOP_FIVE_APP = "TOP_FIVE_APP"; + static inline const char *TOP_SIX_APP = "TOP_SIX_APP"; + static inline const char *TOP_SEVEN_APP = "TOP_SEVEN_APP"; + static inline const char *TOP_EIGHT_APP = "TOP_EIGHT_APP"; + static inline const char *TOP_NINE_APP = "TOP_NINE_APP"; + static inline const char *TOP_TEN_APP = "TOP_TEN_APP"; + + static inline constexpr const char *REMOTE_PASTE_STATE = "REMOTE_PASTE_STATE"; + + // use behaviour key + static inline const char *BOOTTIME = "BOOTTIME"; + static inline const char *WALLTIME = "WALLTIME"; + static inline const char *RESULT = "RESULT"; + static inline const char *OPERATE_APP = "OPERATE_APP"; + static inline const char *PRI_MIME_TYPE = "PRI_MIME_TYPE"; + static inline const char *ISLOCALPASTE = "ISLOCALPASTE"; + static inline const char *ISREMOTE = "ISREMOTE"; + static inline const char *SHAREOPTION = "SHAREOPTION"; + + static inline const int INIT_COPY_TIME_SONSUMING = 7; + static inline const int INIT_PASTE_TIME_SONSUMING = 8; + static inline constexpr const int INIT_REMOTE_PASTE_TIME_SONSUMING = 9; +}; +} // namespace MiscServices +} // namespace OHOS +#endif // MISCSERVICES_PASTEBOARD_HI_VIEW_ADAPTER_H diff --git a/pasteboard/services/dfx/src/pasteboard_dump_helper.cpp b/pasteboard/services/dfx/src/pasteboard_dump_helper.cpp new file mode 100644 index 00000000..b41af6bd --- /dev/null +++ b/pasteboard/services/dfx/src/pasteboard_dump_helper.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "pasteboard_dump_helper.h" + +#include + +namespace OHOS { +namespace MiscServices { +bool PasteboardDumpHelper::Dump(int fd, const std::vector &args) const +{ + dprintf(fd, "\n---------------------------------\n"); + if (args.empty() || args.at(0) == "-h") { + printf("\n%-15s: %-20s", "Option", "Description"); + for (auto &[key, handler] : cmdHandler) { + dprintf(fd, "\n%-15s: %-20s\n", handler->GetFormat().c_str(), handler->ShowHelp().c_str()); + } + return false; + } + auto handler = cmdHandler.find(args.at(0)); + if (handler != cmdHandler.end()) { + std::string output; + handler->second->DoAction(args, output); + dprintf(fd, "%s\n", output.c_str()); + return true; + } + return false; +} +void PasteboardDumpHelper::RegisterCommand(std::shared_ptr &cmd) +{ + cmdHandler.insert(std::make_pair(cmd->GetOption(), cmd)); +} + +PasteboardDumpHelper &PasteboardDumpHelper::GetInstance() +{ + static PasteboardDumpHelper instance; + return instance; +} +} // namespace MiscServices +} // namespace OHOS diff --git a/pasteboard/services/dfx/src/pasteboard_dump_helper.h b/pasteboard/services/dfx/src/pasteboard_dump_helper.h new file mode 100644 index 00000000..e0b3ccdd --- /dev/null +++ b/pasteboard/services/dfx/src/pasteboard_dump_helper.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MISCSERVICES_PASTEBOARD_DUMPE_HELPER_H +#define MISCSERVICES_PASTEBOARD_DUMPE_HELPER_H + +#include +#include +#include +#include + +#include "command.h" + +namespace OHOS { +namespace MiscServices { +class PasteboardDumpHelper { +public: + static PasteboardDumpHelper &GetInstance(); + void RegisterCommand(std::shared_ptr &cmd); + bool Dump(int fd, const std::vector &args) const; + +private: + std::map> cmdHandler; +}; +} // namespace MiscServices +} // namespace OHOS + +#endif // MISCSERVICES_PASTEBOARD_DUMPE_HELPER_H diff --git a/pasteboard/services/dfx/src/pasteboard_trace.cpp b/pasteboard/services/dfx/src/pasteboard_trace.cpp new file mode 100644 index 00000000..264922f2 --- /dev/null +++ b/pasteboard/services/dfx/src/pasteboard_trace.cpp @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "MiscPasteboardDfx" + +#include "pasteboard_trace.h" + +#include +#include + +#include "hitrace/trace.h" +#include "hitrace_meter.h" +#include "pasteboard_hilog.h" + +namespace OHOS { +namespace MiscServices { +static constexpr uint64_t BYTRACE_LABEL = HITRACE_TAG_MISC; +using OHOS::HiviewDFX::HiTraceChain; +using namespace MiscServices; + +std::atomic_bool PasteboardTrace::isSetBytraceEnabled_ = false; + +PasteboardTrace::PasteboardTrace(const std::string &value) +{ + SetBytraceEnable(); + StartTrace(BYTRACE_LABEL, value); +} + +PasteboardTrace::~PasteboardTrace() +{ + FinishTrace(BYTRACE_LABEL); +} + +bool PasteboardTrace::SetBytraceEnable() const +{ + if (isSetBytraceEnabled_.exchange(true)) { + return true; + } + UpdateTraceLabel(); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "success, current tag is true"); + return true; +} +} // namespace MiscServices +} // namespace OHOS diff --git a/pasteboard/services/dfx/src/pasteboard_trace.h b/pasteboard/services/dfx/src/pasteboard_trace.h new file mode 100644 index 00000000..41bbcf51 --- /dev/null +++ b/pasteboard/services/dfx/src/pasteboard_trace.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MISCSERVICES_PASTEBOARD_TRACE_H +#define MISCSERVICES_PASTEBOARD_TRACE_H + +#include +#include + +namespace OHOS { +namespace MiscServices { +class PasteboardTrace { +public: + explicit PasteboardTrace(const std::string &value); + ~PasteboardTrace(); + +private: + bool SetBytraceEnable() const; + static std::atomic_bool isSetBytraceEnabled_; +}; +} // namespace MiscServices +} // namespace OHOS +#endif // MISCSERVICES_PASTEBOARD_TRACE_H diff --git a/pasteboard/services/dfx/src/reporter.cpp b/pasteboard/services/dfx/src/reporter.cpp new file mode 100644 index 00000000..4634099c --- /dev/null +++ b/pasteboard/services/dfx/src/reporter.cpp @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "reporter.h" + +#include "behaviour/pasteboard_behaviour_reporter_impl.h" +#include "fault/pasteboard_fault_impl.h" +#include "statistic/time_consuming_statistic_impl.h" + +namespace OHOS { +namespace MiscServices { +Reporter &Reporter::GetInstance() +{ + static Reporter reporter; + return reporter; +} + +FaultReporter &Reporter::PasteboardFault() +{ + static PasteboardFaultImpl pasteboardFault; + return pasteboardFault; +} + +StatisticReporter &Reporter::TimeConsumingStatistic() +{ + static TimeConsumingStatisticImpl timeConsumingStatistic; + return timeConsumingStatistic; +} + +BehaviourReporter &Reporter::PasteboardBehaviour() +{ + static PasteboardBehaviourReporterImpl pasteboardBehaviourReporter; + return pasteboardBehaviourReporter; +} +} // namespace MiscServices +} // namespace OHOS diff --git a/pasteboard/services/dfx/src/reporter.h b/pasteboard/services/dfx/src/reporter.h new file mode 100644 index 00000000..663ba990 --- /dev/null +++ b/pasteboard/services/dfx/src/reporter.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MISCSERVICES_PASTEBOARD_REPORTER_H +#define MISCSERVICES_PASTEBOARD_REPORTER_H + +#include "behaviour_reporter.h" +#include "dfx_types.h" +#include "fault_reporter.h" +#include "statistic_reporter.h" + +namespace OHOS { +namespace MiscServices { +class Reporter { +public: + static Reporter &GetInstance(); + FaultReporter &PasteboardFault(); + + StatisticReporter &TimeConsumingStatistic(); + + BehaviourReporter &PasteboardBehaviour(); +}; +} // namespace MiscServices +} // namespace OHOS +#endif // MISCSERVICES_PASTEBOARD_REPORTER_H diff --git a/pasteboard/services/dfx/src/statistic/statistic_reporter.h b/pasteboard/services/dfx/src/statistic/statistic_reporter.h new file mode 100644 index 00000000..42ce7756 --- /dev/null +++ b/pasteboard/services/dfx/src/statistic/statistic_reporter.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MISCSERVICES_PASTEBOARD_STATISTIC_REPORTER_H +#define MISCSERVICES_PASTEBOARD_STATISTIC_REPORTER_H + +#include "dfx_types.h" + +namespace OHOS { +namespace MiscServices { +template +class StatisticReporter { +public: + virtual ReportStatus Report(const T &stat) = 0; + virtual ~StatisticReporter() + { + } +}; +} // namespace MiscServices +} // namespace OHOS +#endif // MISCSERVICES_PASTEBOARD_STATISTIC_REPORTER_H \ No newline at end of file diff --git a/pasteboard/services/dfx/src/statistic/time_consuming_statistic_impl.cpp b/pasteboard/services/dfx/src/statistic/time_consuming_statistic_impl.cpp new file mode 100644 index 00000000..6eac5dc5 --- /dev/null +++ b/pasteboard/services/dfx/src/statistic/time_consuming_statistic_impl.cpp @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "time_consuming_statistic_impl.h" + +#include "dfx_code_constant.h" +#include "hiview_adapter.h" + +namespace OHOS { +namespace MiscServices { +ReportStatus TimeConsumingStatisticImpl::Report(const TimeConsumingStat &stat) +{ + HiViewAdapter::ReportTimeConsumingStatistic(stat); + return ReportStatus::SUCCESS; +} +} // namespace MiscServices +} // namespace OHOS diff --git a/pasteboard/services/dfx/src/statistic/time_consuming_statistic_impl.h b/pasteboard/services/dfx/src/statistic/time_consuming_statistic_impl.h new file mode 100644 index 00000000..6d91d3f3 --- /dev/null +++ b/pasteboard/services/dfx/src/statistic/time_consuming_statistic_impl.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MISCSERVICES_PASTEBOARD_TIMECONSUMING_STATISTIC_IMPL_H +#define MISCSERVICES_PASTEBOARD_TIMECONSUMING_STATISTIC_IMPL_H + +#include "dfx_types.h" +#include "statistic_reporter.h" + +namespace OHOS { +namespace MiscServices { +class TimeConsumingStatisticImpl : public StatisticReporter { +public: + virtual ~TimeConsumingStatisticImpl() + { + } + ReportStatus Report(const TimeConsumingStat &stat) override; +}; +} // namespace MiscServices +} // namespace OHOS +#endif // MISCSERVICES_PASTEBOARD_TIMECONSUMING_STATISTIC_IMPL_H diff --git a/pasteboard/services/dialog/BUILD.gn b/pasteboard/services/dialog/BUILD.gn new file mode 100644 index 00000000..f5a6247e --- /dev/null +++ b/pasteboard/services/dialog/BUILD.gn @@ -0,0 +1,51 @@ +# Copyright (c) 2022-2023 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") + +group("pasteboard_dialog") { + deps = [ ":pasteboard_dialog_hap" ] +} + +ohos_hap("pasteboard_dialog_hap") { + hap_profile = "PasteboardDialog/entry/src/main/module.json" + + deps = [ + ":pasteboard_dialog_js_assets", + ":pasteboard_dialog_resources", + ] + + certificate_profile = + "PasteboardDialog/signature/com.ohos.pasteboarddialog.p7b" + hap_name = "pasteboard_dialog" + subsystem_name = "applications" + part_name = "prebuilt_hap" + module_install_dir = "app/com.ohos.pasteboarddialog" +} + +ohos_js_assets("pasteboard_dialog_js_assets") { + hap_profile = "PasteboardDialog/entry/src/main/module.json" + ets2abc = true + source_dir = "PasteboardDialog/entry/src/main/ets" +} + +ohos_app_scope("pasteboard_dialog_app_profile") { + app_profile = "PasteboardDialog/AppScope/app.json" + sources = [ "PasteboardDialog/AppScope/resources" ] +} + +ohos_resources("pasteboard_dialog_resources") { + sources = [ "PasteboardDialog/entry/src/main/resources" ] + deps = [ ":pasteboard_dialog_app_profile" ] + hap_profile = "PasteboardDialog/entry/src/main/module.json" +} diff --git a/pasteboard/services/dialog/PasteboardDialog/.gitignore b/pasteboard/services/dialog/PasteboardDialog/.gitignore new file mode 100644 index 00000000..91d237bb --- /dev/null +++ b/pasteboard/services/dialog/PasteboardDialog/.gitignore @@ -0,0 +1,5 @@ +/node_modules +/local.properties +/.idea +**/build +/.hvigor \ No newline at end of file diff --git a/pasteboard/services/dialog/PasteboardDialog/AppScope/app.json b/pasteboard/services/dialog/PasteboardDialog/AppScope/app.json new file mode 100644 index 00000000..de7c9b43 --- /dev/null +++ b/pasteboard/services/dialog/PasteboardDialog/AppScope/app.json @@ -0,0 +1,13 @@ +{ + "app": { + "bundleName": "com.ohos.pasteboarddialog", + "vendor": "example", + "versionCode": 1000000, + "versionName": "1.0.0", + "icon": "$media:app_icon", + "label": "$string:app_name", + "distributedNotificationEnabled": true, + "minAPIVersion": 9, + "targetAPIVersion": 9 + } +} \ No newline at end of file diff --git a/pasteboard/services/dialog/PasteboardDialog/AppScope/resources/base/element/string.json b/pasteboard/services/dialog/PasteboardDialog/AppScope/resources/base/element/string.json new file mode 100644 index 00000000..b608223e --- /dev/null +++ b/pasteboard/services/dialog/PasteboardDialog/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "app_name", + "value": "PasteboardDialog" + } + ] +} diff --git a/pasteboard/services/dialog/PasteboardDialog/AppScope/resources/base/media/app_icon.png b/pasteboard/services/dialog/PasteboardDialog/AppScope/resources/base/media/app_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c GIT binary patch literal 6790 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 { + const toastRect = { + left: 0, + top: 0, + width: display.width, + height: display.height, + }; + ToastInfo.getInstance().fromAppName = want.parameters.fromAppName; + ToastInfo.getInstance().toAppName = want.parameters.toAppName; + ToastInfo.getInstance().displayHeight = display.height / display.densityPixels - DISTANCE_NUMBER; + this.createToastWindow('PasteboardToast' + new Date().getTime(), toastRect); + }) + .catch((err) => { + hilog.info(0, TAG, 'getDefaultDisplay err: ' + JSON.stringify(err)); + }); + return new ToastStub('PasteboardToast'); + } + + onRequest(want: Want, startId: number): void { + hilog.info(0, TAG, 'onRequest'); + this.onConnect(want); + } + + onDisconnet(): void { + hilog.info(0, TAG, 'onDisconnet'); + this.onDestroy(); + } + + onDestroy(): void { + hilog.info(0, TAG, 'onDestroy'); + GlobalExtensionWindow.getInstance().extensionWin.destroyWindow(); + GlobalContext.getInstance().context.terminateSelf(); + } + + private async createToastWindow(name: string, rect: IRect): Promise { + hilog.info(0, TAG, 'create toast begin'); + + if (globalThis.windowNum > 0) { + globalThis.windowNum = 0; + this.onDestroy(); + } + let windowClass = null; + let config = { + name, + windowType: window.WindowType.TYPE_FLOAT, + ctx: this.context, + }; + try { + window.createWindow(config, (err, data) => { + if (err.code) { + hilog.error(0, TAG, 'Failed to create the window. Cause: ' + JSON.stringify(err)); + return; + } + windowClass = data; + GlobalExtensionWindow.getInstance().extensionWin = data; + hilog.info(0, TAG, 'Succeeded in creating the window. Data: ' + JSON.stringify(data)); + try { + windowClass.setUIContent('pages/index', (err) => { + if (err.code) { + hilog.error(0, TAG, 'Failed to load the content. Cause:' + JSON.stringify(err)); + return; + } + windowClass.moveWindowTo(rect.left, rect.top); + windowClass.resize(rect.width, rect.height); + windowClass.setBackgroundColor('#00000000'); + windowClass.setWindowTouchable(false); + windowClass.showWindow(); + globalThis.windowNum++; + hilog.info(0, TAG, 'Create window successfully'); + }); + } catch (exception) { + hilog.error(0, TAG, 'Failed to load the content. Cause:' + JSON.stringify(exception)); + } + }); + } catch (exception) { + hilog.error(0, TAG, 'Failed to create the window. Cause: ' + JSON.stringify(exception)); + } + } +} diff --git a/pasteboard/services/dialog/PasteboardDialog/entry/src/main/ets/pages/index.ets b/pasteboard/services/dialog/PasteboardDialog/entry/src/main/ets/pages/index.ets new file mode 100644 index 00000000..49e8d97a --- /dev/null +++ b/pasteboard/services/dialog/PasteboardDialog/entry/src/main/ets/pages/index.ets @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + import { ToastInfo } from '../ServiceExtAbility/ToastExtensionAbility'; + +@Entry +@Component +struct Index { + @State fromAppName: string = 'Unknown'; + @State toAppName: string = 'Unknown'; + @State toastHeight: number = 0; + + async aboutToAppear() { + this.fromAppName = ToastInfo.getInstance().fromAppName; + this.toAppName = ToastInfo.getInstance().toAppName; + this.toastHeight = ToastInfo.getInstance().displayHeight; + } + + build() { + Row() { + Column() { + Text() { + Span(this.toAppName).fontSize(14) + .fontWeight(FontWeight.Regular).fontColor($r('app.color.white')).fontFamily($r('app.string.typeface')) + Span($r('app.string.read')).fontSize(14) + .fontWeight(FontWeight.Regular).fontColor($r('app.color.white')).fontFamily($r('app.string.typeface')) + Span(this.fromAppName).fontSize(14) + .fontWeight(FontWeight.Regular).fontColor($r('app.color.white')).fontFamily($r('app.string.typeface')) + Span($r('app.string.info')).fontSize(14) + .fontWeight(FontWeight.Regular).fontColor($r('app.color.white')).fontFamily($r('app.string.typeface')) + } + .height(19) + .opacity(0.6) + .margin({ left: 16, right: 16, top:8, bottom:8 }) + } + .height(36) + .backgroundColor($r('app.color.grey')) + .borderRadius(18) + .alignItems(HorizontalAlign.Center) + .justifyContent(FlexAlign.Center) + } + .alignItems(VerticalAlign.Bottom) + .justifyContent(FlexAlign.Center) + .height(this.toastHeight) + .width('100%') + } +} \ No newline at end of file diff --git a/pasteboard/services/dialog/PasteboardDialog/entry/src/main/module.json b/pasteboard/services/dialog/PasteboardDialog/entry/src/main/module.json new file mode 100644 index 00000000..53a5a623 --- /dev/null +++ b/pasteboard/services/dialog/PasteboardDialog/entry/src/main/module.json @@ -0,0 +1,29 @@ +{ + "module": { + "name": "entry", + "type": "entry", + "srcEntrance": "./ets/Application/MyAbilityStage.ts", + "description": "$string:entry_desc", + "mainElement": "MainAbility", + "deviceTypes": [ + "default", + "tablet", + "2in1" + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:main_pages", + "abilities": [], + "extensionAbilities": [ + { + "name": "ToastExtensionAbility", + "srcEntrance": "./ets/ServiceExtAbility/ToastExtensionAbility.ts", + "description": "$string:ToastExtensionAbility_desc", + "icon": "$media:icon", + "label":"$string:ToastExtensionAbility_label", + "visible": false, + "type": "service" + } + ] + } +} \ No newline at end of file diff --git a/pasteboard/services/dialog/PasteboardDialog/entry/src/main/resources/base/element/color.json b/pasteboard/services/dialog/PasteboardDialog/entry/src/main/resources/base/element/color.json new file mode 100644 index 00000000..2808fe28 --- /dev/null +++ b/pasteboard/services/dialog/PasteboardDialog/entry/src/main/resources/base/element/color.json @@ -0,0 +1,12 @@ +{ + "color": [ + { + "name": "white", + "value": "#FFFFFF" + }, + { + "name": "grey", + "value": "#4D4D4D" + } + ] +} \ No newline at end of file diff --git a/pasteboard/services/dialog/PasteboardDialog/entry/src/main/resources/base/element/string.json b/pasteboard/services/dialog/PasteboardDialog/entry/src/main/resources/base/element/string.json new file mode 100644 index 00000000..2ef736d1 --- /dev/null +++ b/pasteboard/services/dialog/PasteboardDialog/entry/src/main/resources/base/element/string.json @@ -0,0 +1,54 @@ +{ + "string": [ + { + "name": "entry_desc", + "value": "Pasteboard dialog" + }, + { + "name": "ExtensionAbility_desc", + "name": "DialogExtensionAbility_desc", + "value": "Pasteboard dialog extension" + }, + { + "name": "ExtensionAbility_label", + "name": "DialogExtensionAbility_label", + "value": "Pasteboard Dialog" + }, + { + "name": "ToastExtensionAbility_desc", + "value": "Pasteboard toast extension" + }, + { + "name": "ToastExtensionAbility_label", + "value": "Pasteboard Toast" + }, + { + "name": "title", + "value": "pasting to" + }, + { + "name": "typeface", + "value": "HarmonyHeiTi" + }, + { + "name": "from", + "value": "from" + }, + { + "name": "done", + "value": "pasted to" + }, + { + "name": "cancel", + "value": "canceled" + }, + { + "name": "read", + "value": "has read" + }, + { + "name": "info", + "value": "pasteboard information" + } + ] +} \ No newline at end of file diff --git a/pasteboard/services/dialog/PasteboardDialog/entry/src/main/resources/base/media/btn_cancel.svg b/pasteboard/services/dialog/PasteboardDialog/entry/src/main/resources/base/media/btn_cancel.svg new file mode 100644 index 00000000..75c11640 --- /dev/null +++ b/pasteboard/services/dialog/PasteboardDialog/entry/src/main/resources/base/media/btn_cancel.svg @@ -0,0 +1,13 @@ + + + Public/ic_public_input_cancel + + + + + + + + + + \ No newline at end of file diff --git a/pasteboard/services/dialog/PasteboardDialog/entry/src/main/resources/base/media/icon.png b/pasteboard/services/dialog/PasteboardDialog/entry/src/main/resources/base/media/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c GIT binary patch literal 6790 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 2.1.2 < 3.0.0" + } + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://repo.huaweicloud.com/repository/npm/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://repo.huaweicloud.com/repository/npm/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ini": { + "version": "1.3.8", + "resolved": "https://repo.huaweicloud.com/repository/npm/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "interpret": { + "version": "1.4.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/interpret/-/interpret-1.4.0.tgz", + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==" + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha512-xgs2NH9AE66ucSq4cNG1nhSFghr5l6tdL15Pk+jl46bmmBapgoaY/AacXyaDznAqmGL99TiLSQgO/XazFSKYeQ==" + }, + "is-absolute": { + "version": "1.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/is-absolute/-/is-absolute-1.0.0.tgz", + "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", + "requires": { + "is-relative": "^1.0.0", + "is-windows": "^1.0.1" + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" + }, + "is-core-module": { + "version": "2.10.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/is-core-module/-/is-core-module-2.10.0.tgz", + "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==", + "requires": { + "has": "^1.0.3" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "is-glob": { + "version": "4.0.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" + }, + "is-plain-object": { + "version": "5.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==" + }, + "is-relative": { + "version": "1.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/is-relative/-/is-relative-1.0.0.tgz", + "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", + "requires": { + "is-unc-path": "^1.0.0" + } + }, + "is-stream": { + "version": "2.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==" + }, + "is-unc-path": { + "version": "1.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/is-unc-path/-/is-unc-path-1.0.0.tgz", + "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", + "requires": { + "unc-path-regex": "^0.1.2" + } + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q==" + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==" + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==" + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "json5": { + "version": "2.2.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", + "requires": { + "minimist": "^1.2.5" + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha512-YiGkH6EnGrDGqLMITnGjXtGmNtjoXw9SVUzcaos8RBi7Ps0VBylkq+vOcY9QE5poLasPCR849ucFUkl0UzUyOw==", + "requires": { + "invert-kv": "^1.0.0" + } + }, + "liftoff": { + "version": "4.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/liftoff/-/liftoff-4.0.0.tgz", + "integrity": "sha512-rMGwYF8q7g2XhG2ulBmmJgWv25qBsqRbDn5gH0+wnuyeFt7QBJlHJmtg5qEdn4pN6WVAUMgXnIxytMFRX9c1aA==", + "requires": { + "extend": "^3.0.2", + "findup-sync": "^5.0.0", + "fined": "^2.0.0", + "flagged-respawn": "^2.0.0", + "is-plain-object": "^5.0.0", + "object.map": "^1.0.1", + "rechoir": "^0.8.0", + "resolve": "^1.20.0" + } + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha512-cy7ZdNRXdablkXYNI049pthVeXFurRyb9+hA/dZzerZ0pGTx42z+y+ssxBaVV2l70t1muq5IdKhn4UtcoGUY9A==", + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + } + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://repo.huaweicloud.com/repository/npm/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "log4js": { + "version": "6.4.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/log4js/-/log4js-6.4.1.tgz", + "integrity": "sha512-iUiYnXqAmNKiIZ1XSAitQ4TmNs8CdZYTAWINARF3LjnsLN8tY5m0vRwd6uuWj/yNY0YHxeZodnbmxKFUOM2rMg==", + "requires": { + "date-format": "^4.0.3", + "debug": "^4.3.3", + "flatted": "^3.2.4", + "rfdc": "^1.3.0", + "streamroller": "^3.0.2" + } + }, + "make-iterator": { + "version": "1.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/make-iterator/-/make-iterator-1.0.1.tgz", + "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", + "requires": { + "kind-of": "^6.0.2" + } + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==" + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" + }, + "micromatch": { + "version": "4.0.5", + "resolved": "https://repo.huaweicloud.com/repository/npm/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "requires": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + } + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.6", + "resolved": "https://repo.huaweicloud.com/repository/npm/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" + }, + "ms": { + "version": "2.1.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "mute-stdout": { + "version": "1.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/mute-stdout/-/mute-stdout-1.0.0.tgz", + "integrity": "sha512-MaSQenn0f9oxIjtCufclpV00MuYTiHaXPbdcfPIM+quMqoa8cXywjHHx4LhhIAZlXqPWMdcUpYviajfmHtHRJw==" + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "requires": { + "path-key": "^3.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==" + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" + }, + "object.assign": { + "version": "4.1.4", + "resolved": "https://repo.huaweicloud.com/repository/npm/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + } + }, + "object.defaults": { + "version": "1.1.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/object.defaults/-/object.defaults-1.1.0.tgz", + "integrity": "sha512-c/K0mw/F11k4dEUBMW8naXUuBuhxRCfG7W+yFy8EcijU/rSmazOUd1XAEEe6bC0OuXY4HUKjTJv7xbxIMqdxrA==", + "requires": { + "array-each": "^1.0.1", + "array-slice": "^1.0.0", + "for-own": "^1.0.0", + "isobject": "^3.0.0" + } + }, + "object.map": { + "version": "1.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/object.map/-/object.map-1.0.1.tgz", + "integrity": "sha512-3+mAJu2PLfnSVGHwIWubpOFLscJANBKuB/6A4CxBstc4aqwQY0FWcsppuy4jU5GSB95yES5JHSI+33AWuS4k6w==", + "requires": { + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==", + "requires": { + "isobject": "^3.0.1" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "5.1.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "os-locale": { + "version": "1.4.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha512-PRT7ZORmwu2MEFt4/fv3Q+mEfN4zetKxufQrkShY2oGvUms9r8otu5HfdyIFHkYXjO7laNsoVGmM2MANfuTA8g==", + "requires": { + "lcid": "^1.0.0" + } + }, + "parse-filepath": { + "version": "1.0.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/parse-filepath/-/parse-filepath-1.0.2.tgz", + "integrity": "sha512-FwdRXKCohSVeXqwtYonZTXtbGJKrn+HNyWDYVcp5yuJlesTwNH4rsmRZ+GrKAPJ5bLpRxESMeS+Rl0VCHRvB2Q==", + "requires": { + "is-absolute": "^1.0.0", + "map-cache": "^0.2.0", + "path-root": "^0.1.1" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha512-QR/GGaKCkhwk1ePQNYDRKYZ3mwU9ypsKhB0XyFnLQdomyEqk3e8wpW3V5Jp88zbxK4n5ST1nqo+g9juTpownhQ==", + "requires": { + "error-ex": "^1.2.0" + } + }, + "parse-passwd": { + "version": "1.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==" + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha512-yTltuKuhtNeFJKa1PiRzfLAU5182q1y4Eb4XCJ3PBqyzEDkAZRzBrKKBct682ls9reBVHf9udYLN5Nd+K1B9BQ==", + "requires": { + "pinkie-promise": "^2.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" + }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://repo.huaweicloud.com/repository/npm/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "path-root": { + "version": "0.1.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/path-root/-/path-root-0.1.1.tgz", + "integrity": "sha512-QLcPegTHF11axjfojBIoDygmS2E3Lf+8+jI6wOVmNVenrKSo3mFdSGiIgdSHenczw3wPtlVMQaFVwGmM7BJdtg==", + "requires": { + "path-root-regex": "^0.1.0" + } + }, + "path-root-regex": { + "version": "0.1.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/path-root-regex/-/path-root-regex-0.1.2.tgz", + "integrity": "sha512-4GlJ6rZDhQZFE0DPVKh0e9jmZ5egZfxTkp7bcRDuPlJXbAwhxcl2dINPUAsjLdejqaLsCeg8axcLjIbvBjN4pQ==" + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha512-S4eENJz1pkiQn9Znv33Q+deTOKmbl+jj1Fl+qiP/vYezj+S8x+J3Uo0ISrx/QoEvIlOaDWJhPaRd1flJ9HXZqg==", + "requires": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "picomatch": { + "version": "2.3.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" + }, + "pify": { + "version": "2.3.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==" + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://repo.huaweicloud.com/repository/npm/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==" + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==", + "requires": { + "pinkie": "^2.0.0" + } + }, + "pretty-hrtime": { + "version": "1.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/pretty-hrtime/-/pretty-hrtime-1.0.0.tgz", + "integrity": "sha512-CU2l5CYUAptUYq/671ajexQfXuxJFwwg0n243Kdkx8bTjeenedsWgu8TGHPm03vLfNtk3aTXgySKPp3Usykudw==" + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha512-7BGwRHqt4s/uVbuyoeejRn4YmFnYZiFl4AuaeXHlgZf3sONF0SOGlxs2Pw8g6hCKupo08RafIO5YXFNOKTfwsQ==", + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha512-WD9MTlNtI55IwYUS27iHh9tK3YoIVhxis8yKhLpTqWtml739uXc9NWTpxoHkfZf3+DkCCsXox94/VWZniuZm6A==", + "requires": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + } + }, + "rechoir": { + "version": "0.8.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/rechoir/-/rechoir-0.8.0.tgz", + "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==", + "requires": { + "resolve": "^1.20.0" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==" + }, + "require-from-string": { + "version": "2.0.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==" + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha512-IqSUtOVP4ksd1C/ej5zeEh/BIP2ajqpn8c5x+q99gvcIG/Qf0cud5raVnE/Dwd0ua9TXYDoDc0RE5hBSdz22Ug==" + }, + "resolve": { + "version": "1.22.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/resolve/-/resolve-1.22.1.tgz", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "requires": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "resolve-dir": { + "version": "1.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha512-R7uiTjECzvOsWSfdM0QKFNBVFcK27aHOUwdvK53BcW8zqnGdYp0Fbj82cy54+2A4P2tFM22J5kRfe1R+lM/1yg==", + "requires": { + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" + } + }, + "resolve-package-path": { + "version": "4.0.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/resolve-package-path/-/resolve-package-path-4.0.3.tgz", + "integrity": "sha512-SRpNAPW4kewOaNUt8VPqhJ0UMxawMwzJD8V7m1cJfdSTK9ieZwS6K7Dabsm4bmLFM96Z5Y/UznrpG5kt1im8yA==", + "requires": { + "path-root": "^0.1.1" + } + }, + "rfdc": { + "version": "1.3.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "semver": { + "version": "5.7.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" + }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://repo.huaweicloud.com/repository/npm/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "spdx-correct": { + "version": "3.1.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==" + }, + "spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.12", + "resolved": "https://repo.huaweicloud.com/repository/npm/spdx-license-ids/-/spdx-license-ids-3.0.12.tgz", + "integrity": "sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA==" + }, + "streamroller": { + "version": "3.1.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/streamroller/-/streamroller-3.1.3.tgz", + "integrity": "sha512-CphIJyFx2SALGHeINanjFRKQ4l7x2c+rXYJ4BMq0gd+ZK0gi4VT8b+eHe2wi58x4UayBAKx4xtHpXT/ea1cz8w==", + "requires": { + "date-format": "^4.0.14", + "debug": "^4.3.4", + "fs-extra": "^8.1.0" + }, + "dependencies": { + "fs-extra": { + "version": "8.1.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" + } + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw==", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha512-kwrX1y7czp1E69n2ajbG65mIo9dqvJ+8aBQXOGVxqwvNbsXdFM6Lq37dLAY3mknUwru8CfcCbfOLL/gMo+fi3g==", + "requires": { + "is-utf8": "^0.2.0" + } + }, + "strip-final-newline": { + "version": "2.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==" + }, + "strnum": { + "version": "1.0.5", + "resolved": "https://repo.huaweicloud.com/repository/npm/strnum/-/strnum-1.0.5.tgz", + "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==" + }, + "supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==" + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "requires": { + "is-number": "^7.0.0" + } + }, + "unc-path-regex": { + "version": "0.1.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/unc-path-regex/-/unc-path-regex-0.1.2.tgz", + "integrity": "sha512-eXL4nmJT7oCpkZsHZUOJo8hcX3GbsiDOa0Qu9F646fi8dT3XuSVopVqAcEiVzSKKH7UoDti23wNX3qGFxcW5Qg==" + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" + }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "requires": { + "punycode": "^2.1.0" + } + }, + "v8flags": { + "version": "3.2.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/v8flags/-/v8flags-3.2.0.tgz", + "integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==", + "requires": { + "homedir-polyfill": "^1.0.1" + } + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://repo.huaweicloud.com/repository/npm/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "1.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/which-module/-/which-module-1.0.0.tgz", + "integrity": "sha512-F6+WgncZi/mJDrammbTuHe1q0R5hOXv/mBaiNA2TCNT/LTHusX0V+CJnj9XT8ki5ln2UZyyddDgHfCzyrOH7MQ==" + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha512-vAaEaDM946gbNpH5pLVNR+vX2ht6n0Bt3GXwVB1AuAqZosOvHNF3P7wDnh8KLkSqgUh0uh77le7Owgoz+Z9XBw==", + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "y18n": { + "version": "3.2.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/y18n/-/y18n-3.2.2.tgz", + "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==" + }, + "yargs": { + "version": "7.1.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/yargs/-/yargs-7.1.2.tgz", + "integrity": "sha512-ZEjj/dQYQy0Zx0lgLMLR8QuaqTihnxirir7EwUHp1Axq4e3+k8jXU5K0VLbNvedv1f4EWtBonDIZm0NUr+jCcA==", + "requires": { + "camelcase": "^3.0.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^1.4.0", + "read-pkg-up": "^1.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^1.0.2", + "which-module": "^1.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^5.0.1" + } + }, + "yargs-parser": { + "version": "5.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/yargs-parser/-/yargs-parser-5.0.1.tgz", + "integrity": "sha512-wpav5XYiddjXxirPoCTUPbqM0PXvJ9hiBMvuJgInvo4/lAOTZzUprArw17q2O1P2+GHhbBr18/iQwjL5Z9BqfA==", + "requires": { + "camelcase": "^3.0.0", + "object.assign": "^4.1.0" + } + } + } +} diff --git a/pasteboard/services/dialog/PasteboardDialog/package.json b/pasteboard/services/dialog/PasteboardDialog/package.json new file mode 100644 index 00000000..f64cccd5 --- /dev/null +++ b/pasteboard/services/dialog/PasteboardDialog/package.json @@ -0,0 +1,17 @@ +{ + "name": "pasteboarddialog", + "version": "1.0.0", + "ohos": { + "org": "huawei", + "buildTool": "hvigor", + "directoryLevel": "project" + }, + "description": "example description", + "repository": {}, + "license": "ISC", + "dependencies": { + "@ohos/hypium": "1.0.2", + "@ohos/hvigor": "1.2.2", + "@ohos/hvigor-ohos-plugin": "1.2.2" + } +} diff --git a/pasteboard/services/dialog/PasteboardDialog/signature/com.ohos.pasteboarddialog.p7b b/pasteboard/services/dialog/PasteboardDialog/signature/com.ohos.pasteboarddialog.p7b new file mode 100644 index 0000000000000000000000000000000000000000..75888be5c0557d6f4bcc24a22c1bb832c9fce8d2 GIT binary patch literal 3430 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 aw**^+?RbCJm4nx~XI{INnKd_W{eJ features; + std::vector plugins; + std::vector components; + bool Marshal(json &node) const override; + bool Unmarshal(const json &node) override; +}; +} // namespace OHOS::MiscServices +#endif // OHOS_PASTEBOARD_SERVICES_LOAD_CONFIG_H diff --git a/pasteboard/services/load/include/loader.h b/pasteboard/services/load/include/loader.h new file mode 100644 index 00000000..492c49fd --- /dev/null +++ b/pasteboard/services/load/include/loader.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_PASTEBOARD_SERVICES_LOAD_LOADER_H +#define OHOS_PASTEBOARD_SERVICES_LOAD_LOADER_H +#include "config.h" +namespace OHOS::MiscServices { +class Loader { +public: + Loader(); + ~Loader(); + void LoadComponents(); + +private: + using Constructor = void (*)(const char *); + Config LoadConfig(); + static constexpr const char *CONF_FILE = "/system/etc/pasteboard/conf/pasteboard.json"; +}; +} // namespace OHOS::MiscServices +#endif // OHOS_PASTEBOARD_SERVICES_LOAD_LOADER_H diff --git a/pasteboard/services/load/src/config.cpp b/pasteboard/services/load/src/config.cpp new file mode 100644 index 00000000..f2893d3a --- /dev/null +++ b/pasteboard/services/load/src/config.cpp @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "config.h" +namespace OHOS::MiscServices { +bool Config::Component::Marshal(Serializable::json &node) const +{ + SetValue(node, description, GET_NAME(description)); + SetValue(node, lib, GET_NAME(lib)); + SetValue(node, constructor, GET_NAME(constructor)); + SetValue(node, destructor, GET_NAME(destructor)); + SetValue(node, params, GET_NAME(params)); + return true; +} + +bool Config::Component::Unmarshal(const Serializable::json &node) +{ + GetValue(node, GET_NAME(description), description); + GetValue(node, GET_NAME(lib), lib); + GetValue(node, GET_NAME(constructor), constructor); + GetValue(node, GET_NAME(destructor), destructor); + GetValue(node, GET_NAME(params), params); + return true; +} + +bool Config::Marshal(Serializable::json &node) const +{ + SetValue(node, processLabel, GET_NAME(processLabel)); + SetValue(node, version, GET_NAME(version)); + SetValue(node, features, GET_NAME(features)); + SetValue(node, plugins, GET_NAME(plugins)); + SetValue(node, components, GET_NAME(components)); + return true; +} + +bool Config::Unmarshal(const Serializable::json &node) +{ + GetValue(node, GET_NAME(processLabel), processLabel); + GetValue(node, GET_NAME(version), version); + GetValue(node, GET_NAME(features), features); + GetValue(node, GET_NAME(plugins), plugins); + GetValue(node, GET_NAME(components), components); + return true; +} +} // namespace OHOS::MiscServices \ No newline at end of file diff --git a/pasteboard/services/load/src/loader.cpp b/pasteboard/services/load/src/loader.cpp new file mode 100644 index 00000000..727995dd --- /dev/null +++ b/pasteboard/services/load/src/loader.cpp @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "loader.h" + +#include +#include + +#include "pasteboard_hilog.h" +namespace OHOS::MiscServices { +Loader::Loader() +{ +} + +Loader::~Loader() +{ +} + +void Loader::LoadComponents() +{ + Config config = LoadConfig(); + for (auto &component : config.components) { + if (component.lib.empty()) { + continue; + } + + // no need to close the component, so we don't keep the handles + auto handle = dlopen(component.lib.c_str(), RTLD_LAZY); + if (handle == nullptr) { + PASTEBOARD_HILOGE( + PASTEBOARD_MODULE_SERVICE, "dlopen(%{public}s) failed(%{public}d)!", component.lib.c_str(), errno); + continue; + } + + if (component.constructor.empty()) { + continue; + } + + auto ctor = reinterpret_cast(dlsym(handle, component.constructor.c_str())); + if (ctor == nullptr) { + continue; + } + ctor(component.params.c_str()); + } +} + +Config Loader::LoadConfig() +{ + Config config; + std::string context; + std::ifstream fin(CONF_FILE); + while (fin.good()) { + std::string line; + std::getline(fin, line); + context += line; + } + config.Unmarshall(context); + return config; +} +} // namespace OHOS::MiscServices \ No newline at end of file diff --git a/pasteboard/services/test/BUILD.gn b/pasteboard/services/test/BUILD.gn new file mode 100644 index 00000000..11ba8d46 --- /dev/null +++ b/pasteboard/services/test/BUILD.gn @@ -0,0 +1,75 @@ +# Copyright (C) 2023 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") +import("//foundation/distributeddatamgr/pasteboard/pasteboard.gni") + +config("module_private_config") { + visibility = [ ":*" ] + + include_dirs = [ + "${pasteboard_innerkits_path}/include", + "${pasteboard_service_path}/dfx/src", + "${pasteboard_service_path}/dfx/src/behaviour", + "${pasteboard_service_path}/dfx/src/fault", + "${pasteboard_service_path}/dfx/src/statistic", + "include", + "unittest/include", + "//base/security/access_token/interfaces/innerkits/accesstoken/include", + "//foundation/distributeddatamgr/pasteboard/framework/tlv", + "//foundation/distributeddatamgr/pasteboard/framework/uri", + ] +} + +module_output_path = "pasteboard/pasteboard_service" + +ohos_unittest("PasteboardServiceTest") { + module_out_path = module_output_path + + sources = [ + "${pasteboard_service_path}/dfx/src/behaviour/pasteboard_behaviour_reporter_impl.cpp", + "${pasteboard_service_path}/dfx/src/fault/pasteboard_fault_impl.cpp", + "${pasteboard_service_path}/dfx/src/reporter.cpp", + "${pasteboard_service_path}/dfx/src/statistic/time_consuming_statistic_impl.cpp", + "unittest/src/dfx_test.cpp", + "unittest/src/paste_service_test.cpp", + ] + configs = [ + "//commonlibrary/c_utils/base:utils_config", + ":module_private_config", + ] + external_deps = [ + "ability_base:want", + "ability_base:zuri", + "access_token:libaccesstoken_sdk", + "c_utils:utils", + "hilog:libhilog", + "image_framework:image_native", + "ipc:ipc_core", + "os_account:os_account_innerkits", + ] + + deps = [ + "${pasteboard_innerkits_path}:pasteboard_client", + "//base/security/access_token/interfaces/innerkits/token_setproc:libtoken_setproc", + "//third_party/googletest:gtest_main", + ] +} + +group("unittest") { + testonly = true + + deps = [] + + deps += [ ":PasteboardServiceTest" ] +} diff --git a/pasteboard/services/test/unittest/include/pasteboard_observer_callback.h b/pasteboard/services/test/unittest/include/pasteboard_observer_callback.h new file mode 100644 index 00000000..3ec8aec7 --- /dev/null +++ b/pasteboard/services/test/unittest/include/pasteboard_observer_callback.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef PASTE_SERVICE_TEST_H +#define PASTE_SERVICE_TEST_H + +#include "pasteboard_error.h" +#include "pasteboard_observer.h" +#include "pasteboard_observer_stub.h" + +namespace OHOS { +namespace MiscServices { +class PasteboardObserverCallback : public PasteboardObserver { +public: + PasteboardObserverCallback(){}; + ~PasteboardObserverCallback() + { + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "deconstructor."); + }; + void OnPasteboardChanged() override; +}; + +class PasteboardEventObserverCallback : public PasteboardObserver { +public: + PasteboardEventObserverCallback() {}; + ~PasteboardEventObserverCallback() + { + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "deconstructor."); + }; + void OnPasteboardEvent(std::string bundleName, int32_t status) override; +}; +} // namespace MiscServices +} // namespace OHOS +#endif // PASTE_SERVICE_TEST_H diff --git a/pasteboard/services/test/unittest/src/dfx_test.cpp b/pasteboard/services/test/unittest/src/dfx_test.cpp new file mode 100644 index 00000000..5ab27777 --- /dev/null +++ b/pasteboard/services/test/unittest/src/dfx_test.cpp @@ -0,0 +1,199 @@ +/* +* Copyright (c) 2023 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include + +#include "hiview_adapter.h" +#include "pasteboard_behaviour_reporter_impl.h" +#include "pasteboard_fault_impl.h" +#include "pasteboard_hilog.h" +#include "reporter.h" +#include "time_consuming_statistic_impl.h" + +namespace OHOS::MiscServices { +using namespace testing::ext; +class DFXTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void DFXTest::SetUpTestCase(void) +{ +} + +void DFXTest::TearDownTestCase(void) +{ +} + +void DFXTest::SetUp(void) +{ + HiViewAdapter::StartTimerThread(); +} + +void DFXTest::TearDown(void) +{ +} + +/** +* @tc.name: DFXTest001 +* @tc.desc: test dfx report fault. +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(DFXTest, DFXTest001, TestSize.Level0) +{ + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_INNERKIT, "Start."); + PasteboardFaultMsg faultMsg = { .userId = 1, .errorCode = "error" }; + auto status = Reporter::GetInstance().PasteboardFault().Report(faultMsg); + ASSERT_EQ(status, ReportStatus::SUCCESS); + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_INNERKIT, "End."); +} + +/** +* @tc.name: DFXTest002 +* @tc.desc: test dfx report time consuming statistic with SPS_COPY_STATE. +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(DFXTest, DFXTest002, TestSize.Level0) +{ + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_INNERKIT, "Start."); + TimeConsumingStat timeConsumingStat = { .pasteboardState = SPS_COPY_STATE, .dataSize = -1, .timeConsuming = -1 }; + auto status = Reporter::GetInstance().TimeConsumingStatistic().Report(timeConsumingStat); + ASSERT_EQ(status, ReportStatus::SUCCESS); + + timeConsumingStat = { .pasteboardState = SPS_COPY_STATE, .dataSize = DATA_LEVEL_ONE, .timeConsuming = -1 }; + status = Reporter::GetInstance().TimeConsumingStatistic().Report(timeConsumingStat); + ASSERT_EQ(status, ReportStatus::SUCCESS); + + timeConsumingStat = { + .pasteboardState = SPS_COPY_STATE, .dataSize = DATA_LEVEL_ONE, .timeConsuming = TCS_TIME_CONSUMING_LEVEL_ONE + }; + status = Reporter::GetInstance().TimeConsumingStatistic().Report(timeConsumingStat); + ASSERT_EQ(status, ReportStatus::SUCCESS); + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_INNERKIT, "End."); +} + +/** +* @tc.name: DFXTest003 +* @tc.desc: test dfx report time consuming statistic with SPS_PASTE_STATE. +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(DFXTest, DFXTest003, TestSize.Level0) +{ + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_INNERKIT, "Start."); + TimeConsumingStat timeConsumingStat = { .pasteboardState = SPS_PASTE_STATE, .dataSize = -1, .timeConsuming = -1 }; + auto status = Reporter::GetInstance().TimeConsumingStatistic().Report(timeConsumingStat); + ASSERT_EQ(status, ReportStatus::SUCCESS); + + timeConsumingStat = { .pasteboardState = SPS_PASTE_STATE, .dataSize = DATA_LEVEL_ONE, .timeConsuming = -1 }; + status = Reporter::GetInstance().TimeConsumingStatistic().Report(timeConsumingStat); + ASSERT_EQ(status, ReportStatus::SUCCESS); + + timeConsumingStat = { + .pasteboardState = SPS_PASTE_STATE, .dataSize = DATA_LEVEL_ONE, .timeConsuming = TCS_TIME_CONSUMING_LEVEL_ONE + }; + status = Reporter::GetInstance().TimeConsumingStatistic().Report(timeConsumingStat); + ASSERT_EQ(status, ReportStatus::SUCCESS); + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_INNERKIT, "End."); +} + +/** +* @tc.name: DFXTest004 +* @tc.desc: test dfx report time consuming statistic with SPS_REMOTE_PASTE_STATE. +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(DFXTest, DFXTest004, TestSize.Level0) +{ + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_INNERKIT, "Start."); + TimeConsumingStat timeConsumingStat = { + .pasteboardState = SPS_REMOTE_PASTE_STATE, .dataSize = -1, .timeConsuming = -1 + }; + auto status = Reporter::GetInstance().TimeConsumingStatistic().Report(timeConsumingStat); + ASSERT_EQ(status, ReportStatus::SUCCESS); + + timeConsumingStat = { .pasteboardState = SPS_REMOTE_PASTE_STATE, .dataSize = DATA_LEVEL_ONE, .timeConsuming = -1 }; + status = Reporter::GetInstance().TimeConsumingStatistic().Report(timeConsumingStat); + ASSERT_EQ(status, ReportStatus::SUCCESS); + + timeConsumingStat = { .pasteboardState = SPS_REMOTE_PASTE_STATE, + .dataSize = DATA_LEVEL_ONE, + .timeConsuming = TCS_TIME_CONSUMING_LEVEL_ONE }; + status = Reporter::GetInstance().TimeConsumingStatistic().Report(timeConsumingStat); + ASSERT_EQ(status, ReportStatus::SUCCESS); + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_INNERKIT, "End."); +} + +/** +* @tc.name: DFXTest005 +* @tc.desc: test dfx report time consuming statistic with SPS_INVALID_STATE. +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(DFXTest, DFXTest005, TestSize.Level0) +{ + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_INNERKIT, "Start."); + TimeConsumingStat timeConsumingStat = { + .pasteboardState = SPS_INVALID_STATE, .dataSize = DATA_LEVEL_ONE, .timeConsuming = TCS_TIME_CONSUMING_LEVEL_ONE + }; + auto status = Reporter::GetInstance().TimeConsumingStatistic().Report(timeConsumingStat); + ASSERT_EQ(status, ReportStatus::SUCCESS); + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_INNERKIT, "End."); +} + +/** +* @tc.name: DFXTest006 +* @tc.desc: test dfx report behaviour. +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(DFXTest, DFXTest006, TestSize.Level0) +{ + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_INNERKIT, "Start."); + PasteboardBehaviourMsg behaviourMsg = { .pasteboardState = BPS_COPY_STATE, .bundleName = "com.paste.test" }; + auto status = Reporter::GetInstance().PasteboardBehaviour().Report(behaviourMsg); + ASSERT_EQ(status, ReportStatus::SUCCESS); + status = Reporter::GetInstance().PasteboardBehaviour().Report(behaviourMsg); + ASSERT_EQ(status, ReportStatus::SUCCESS); + + behaviourMsg = { .pasteboardState = BPS_PASTE_STATE, .bundleName = "com.paste.test" }; + status = Reporter::GetInstance().PasteboardBehaviour().Report(behaviourMsg); + ASSERT_EQ(status, ReportStatus::SUCCESS); + status = Reporter::GetInstance().PasteboardBehaviour().Report(behaviourMsg); + ASSERT_EQ(status, ReportStatus::SUCCESS); + + behaviourMsg = { .pasteboardState = BPS_REMOTE_PASTE_STATE, .bundleName = "com.paste.test" }; + status = Reporter::GetInstance().PasteboardBehaviour().Report(behaviourMsg); + ASSERT_EQ(status, ReportStatus::SUCCESS); + status = Reporter::GetInstance().PasteboardBehaviour().Report(behaviourMsg); + ASSERT_EQ(status, ReportStatus::SUCCESS); + + behaviourMsg = { .pasteboardState = BPS_INVALID_STATE, .bundleName = "com.paste.test" }; + status = Reporter::GetInstance().PasteboardBehaviour().Report(behaviourMsg); + ASSERT_EQ(status, ReportStatus::SUCCESS); + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_INNERKIT, "End."); +} +} // namespace OHOS::MiscServices \ No newline at end of file diff --git a/pasteboard/services/test/unittest/src/paste_service_test.cpp b/pasteboard/services/test/unittest/src/paste_service_test.cpp new file mode 100644 index 00000000..cf531379 --- /dev/null +++ b/pasteboard/services/test/unittest/src/paste_service_test.cpp @@ -0,0 +1,1321 @@ +/* + * Copyright (c) 2021-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include + +#include +#include +#include + +#include "access_token.h" +#include "accesstoken_kit.h" +#include "hap_token_info.h" +#include "os_account_manager.h" +#include "pasteboard_client.h" +#include "pasteboard_error.h" +#include "pasteboard_hilog.h" +#include "pasteboard_observer_callback.h" +#include "permission_state_full.h" +#include "pixel_map.h" +#include "token_setproc.h" +#include +#include "uri.h" +#include "want.h" + +namespace OHOS::MiscServices { +using namespace testing::ext; +using namespace OHOS::Media; +using namespace OHOS::Security::AccessToken; +constexpr const char *CMD = "hidumper -s 3701 -a --data"; +constexpr const uint16_t EACH_LINE_LENGTH = 50; +constexpr const uint16_t TOTAL_LENGTH = 500; +std::string g_webviewPastedataTag = "WebviewPasteDataTag"; +class PasteboardServiceTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + static bool ExecuteCmd(std::string &result); + + static void AllocTestTokenId(); + static void DeleteTestTokenId(); + static void SetTestTokenId(); + static void RestoreSelfTokenId(); + static void CommonTest(PasteData &oldPasteData, PasteData &newPasteData); + static sptr pasteboardObserver_; + static sptr pasteboardEventObserver_; + static std::atomic_bool pasteboardChangedFlag_; + static std::atomic_int32_t pasteboardEventStatus_; + static uint64_t selfTokenId_; + static AccessTokenID testTokenId_; +}; +std::atomic_bool PasteboardServiceTest::pasteboardChangedFlag_ = false; +std::atomic_int32_t PasteboardServiceTest::pasteboardEventStatus_ = -1; +sptr PasteboardServiceTest::pasteboardObserver_ = nullptr; +sptr PasteboardServiceTest::pasteboardEventObserver_ = nullptr; +uint64_t PasteboardServiceTest::selfTokenId_ = 0; +AccessTokenID PasteboardServiceTest::testTokenId_ = 0; + +void PasteboardServiceTest::SetUpTestCase(void) +{ + selfTokenId_ = GetSelfTokenID(); + AllocTestTokenId(); +} + +void PasteboardServiceTest::TearDownTestCase(void) +{ + DeleteTestTokenId(); +} + +void PasteboardServiceTest::SetUp(void) +{ +} + +void PasteboardServiceTest::TearDown(void) +{ + if (PasteboardServiceTest::pasteboardObserver_ != nullptr) { + PasteboardClient::GetInstance()->RemovePasteboardEventObserver(PasteboardServiceTest::pasteboardObserver_); + } + if (PasteboardServiceTest::pasteboardEventObserver_ != nullptr) { + PasteboardClient::GetInstance()->RemovePasteboardEventObserver(PasteboardServiceTest::pasteboardEventObserver_); + } + PasteboardClient::GetInstance()->Clear(); + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "TearDown."); +} + +void PasteboardObserverCallback::OnPasteboardChanged() +{ + PasteboardServiceTest::pasteboardChangedFlag_ = true; + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "test changed callback."); +} + +void PasteboardEventObserverCallback::OnPasteboardEvent(std::string bundleName, int32_t status) +{ + PasteboardServiceTest::pasteboardEventStatus_ = status; + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "test event callback bundleName: %{public}s,status:%{public}d", + bundleName.c_str(), status); +} + +bool PasteboardServiceTest::ExecuteCmd(std::string &result) +{ + char buff[EACH_LINE_LENGTH] = { 0x00 }; + char output[TOTAL_LENGTH] = { 0x00 }; + FILE *ptr = nullptr; + if ((ptr = popen(CMD, "r")) != nullptr) { + while (fgets(buff, sizeof(buff), ptr) != nullptr) { + if (strcat_s(output, sizeof(output), buff) != 0) { + pclose(ptr); + ptr = nullptr; + return false; + } + } + pclose(ptr); + ptr = nullptr; + } else { + return false; + } + result = std::string(output); + return true; +} + +void PasteboardServiceTest::AllocTestTokenId() +{ + std::vector ids; + auto ret = AccountSA::OsAccountManager::QueryActiveOsAccountIds(ids); + if (ret != ERR_OK || ids.empty()) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "query active user failed errCode = %{public}d", ret); + return; + } + HapInfoParams infoParams = { + .userID = ids[0], + .bundleName = "ohos.privacy_test.pasteboard", + .instIndex = 0, + .appIDDesc = "privacy_test.pasteboard" + }; + PermissionStateFull testState = { + .permissionName = "ohos.permission.DUMP", + .isGeneral = true, + .resDeviceID = { "local" }, + .grantStatus = { PermissionState::PERMISSION_GRANTED }, + .grantFlags = { 1 } + }; + HapPolicyParams policyParams = { + .apl = APL_NORMAL, + .domain = "test.domain.pasteboard", + .permList = {}, + .permStateList = { testState } + }; + + AccessTokenKit::AllocHapToken(infoParams, policyParams); + testTokenId_ = Security::AccessToken::AccessTokenKit::GetHapTokenID( + infoParams.userID, infoParams.bundleName, infoParams.instIndex); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "userID = %{public}d, testTokenId = 0x%{public}x.", infoParams.userID, + testTokenId_); +} + +void PasteboardServiceTest::DeleteTestTokenId() +{ + AccessTokenKit::DeleteToken(testTokenId_); +} + + +void PasteboardServiceTest::SetTestTokenId() +{ + auto ret = SetSelfTokenID(testTokenId_); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "testTokenId = 0x%{public}x, ret = %{public}d!", testTokenId_, ret); +} + +void PasteboardServiceTest::RestoreSelfTokenId() +{ + auto ret = SetSelfTokenID(selfTokenId_); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "ret = %{public}d!", ret); +} + +void PasteboardServiceTest::CommonTest(PasteData &oldPasteData, PasteData &newPasteData) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "start."); + PasteboardClient::GetInstance()->Clear(); + auto hasPasteData = PasteboardClient::GetInstance()->HasPasteData(); + ASSERT_TRUE(hasPasteData != true); + int32_t ret = PasteboardClient::GetInstance()->SetPasteData(oldPasteData); + ASSERT_TRUE(ret == static_cast(PasteboardError::E_OK)); + hasPasteData = PasteboardClient::GetInstance()->HasPasteData(); + ASSERT_TRUE(hasPasteData == true); + ret = PasteboardClient::GetInstance()->GetPasteData(newPasteData); + ASSERT_TRUE(ret == static_cast(PasteboardError::E_OK)); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "end."); +} + +string GetTime() +{ + time_t curtime; + time(&curtime); + tm *nowtime = localtime(&curtime); + std::string targetTime = std::to_string(1900 + nowtime->tm_year) + "-" + std::to_string(1 + nowtime->tm_mon) + "-" + + std::to_string(nowtime->tm_mday) + " " + std::to_string(nowtime->tm_hour) + ":" + + std::to_string(nowtime->tm_min) + ":" + std::to_string(nowtime->tm_sec); + return targetTime; +} + +/** +* @tc.name: PasteboardTest001 +* @tc.desc: Create paste board test. +* @tc.type: FUNC +*/ +HWTEST_F(PasteboardServiceTest, PasteboardTest001, TestSize.Level0) +{ + auto record = PasteboardClient::GetInstance()->CreatePlainTextRecord("paste record1"); + ASSERT_TRUE(record != nullptr); + std::string plainText = "plain text"; + auto data = PasteboardClient::GetInstance()->CreatePlainTextData(plainText); + ASSERT_TRUE(data != nullptr); + int32_t ret = PasteboardClient::GetInstance()->SetPasteData(*data); + ASSERT_TRUE(ret == static_cast(PasteboardError::E_OK)); + auto has = PasteboardClient::GetInstance()->HasPasteData(); + ASSERT_TRUE(has == true); + PasteData pasteData; + ret = PasteboardClient::GetInstance()->GetPasteData(pasteData); + ASSERT_TRUE(ret == static_cast(PasteboardError::E_OK)); + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "get."); + auto primaryText = pasteData.GetPrimaryText(); + ASSERT_TRUE(primaryText != nullptr); + ASSERT_TRUE(*primaryText == plainText); +} + +/** +* @tc.name: PasteRecordTest001 +* @tc.desc: Create paste board record test. +* @tc.type: FUNC +*/ +HWTEST_F(PasteboardServiceTest, PasteRecordTest001, TestSize.Level0) +{ + std::string plainText = "helloWorld"; + auto record = PasteboardClient::GetInstance()->CreatePlainTextRecord(plainText); + ASSERT_TRUE(record != nullptr); + auto newPlainText = record->GetPlainText(); + ASSERT_TRUE(newPlainText != nullptr); + ASSERT_TRUE(*newPlainText == plainText); +} + +/** +* @tc.name: PasteRecordTest002 +* @tc.desc: Create paste board record test. +* @tc.type: FUNC +*/ +HWTEST_F(PasteboardServiceTest, PasteRecordTest002, TestSize.Level0) +{ + std::string htmlText = "
"; + auto record = PasteboardClient::GetInstance()->CreateHtmlTextRecord(htmlText); + ASSERT_TRUE(record != nullptr); + auto newHtmlText = record->GetHtmlText(); + ASSERT_TRUE(newHtmlText != nullptr); + ASSERT_TRUE(*newHtmlText == htmlText); +} + +/** +* @tc.name: PasteRecordTest003 +* @tc.desc: Create paste board record test. +* @tc.type: FUNC +*/ +HWTEST_F(PasteboardServiceTest, PasteRecordTest003, TestSize.Level0) +{ + using namespace OHOS::AAFwk; + std::shared_ptr want = std::make_shared(); + std::string key = "id"; + int32_t id = 456; + Want wantIn = want->SetParam(key, id); + auto record = PasteboardClient::GetInstance()->CreateWantRecord(want); + ASSERT_TRUE(record != nullptr); + auto newWant = record->GetWant(); + ASSERT_TRUE(newWant != nullptr); + int32_t defaultValue = 333; + ASSERT_TRUE(newWant->GetIntParam(key, defaultValue) == id); +} + +/** +* @tc.name: PasteRecordTest004 +* @tc.desc: Create paste board record test. +* @tc.type: FUNC +*/ +HWTEST_F(PasteboardServiceTest, PasteRecordTest004, TestSize.Level0) +{ + OHOS::Uri uri("uri"); + auto record = PasteboardClient::GetInstance()->CreateUriRecord(uri); + ASSERT_TRUE(record != nullptr); + auto newUri = record->GetUri(); + ASSERT_TRUE(newUri != nullptr); + ASSERT_TRUE(newUri->ToString() == uri.ToString()); +} + +/** +* @tc.name: PasteRecordTest005 +* @tc.desc: Create paste board record test. +* @tc.type: FUNC +* @tc.require: AR000H5GKU +*/ +HWTEST_F(PasteboardServiceTest, PasteRecordTest005, TestSize.Level0) +{ + uint32_t color[100] = { 3, 7, 9, 9, 7, 6 }; + InitializationOptions opts = { { 5, 7 }, PixelFormat::ARGB_8888, PixelFormat::ARGB_8888 }; + std::unique_ptr pixelMap = PixelMap::Create(color, 100, opts); + std::shared_ptr pixelMapIn = move(pixelMap); + auto pasteDataRecord = PasteboardClient::GetInstance()->CreatePixelMapRecord(pixelMapIn); + ASSERT_TRUE(pasteDataRecord != nullptr); + auto newPixelMap = pasteDataRecord->GetPixelMap(); + ASSERT_TRUE(newPixelMap != nullptr); + ImageInfo imageInfo = {}; + newPixelMap->GetImageInfo(imageInfo); + ASSERT_TRUE(imageInfo.size.height == opts.size.height); + ASSERT_TRUE(imageInfo.size.width == opts.size.width); + ASSERT_TRUE(imageInfo.pixelFormat == opts.pixelFormat); +} + +/** +* @tc.name: PasteRecordTest006 +* @tc.desc: Create paste board record test. +* @tc.type: FUNC +* @tc.require: AR000H5GKU +*/ +HWTEST_F(PasteboardServiceTest, PasteRecordTest006, TestSize.Level0) +{ + uint32_t color[100] = { 3, 7, 9, 9, 7, 6 }; + InitializationOptions opts = { { 5, 7 }, PixelFormat::ARGB_8888, PixelFormat::ARGB_8888 }; + std::unique_ptr pixelMap = PixelMap::Create(color, sizeof(color) / sizeof(color[0]), opts); + std::shared_ptr pixelMapIn = move(pixelMap); + auto pasteDataRecord = PasteboardClient::GetInstance()->CreatePixelMapRecord(pixelMapIn); + ASSERT_TRUE(pasteDataRecord != nullptr); + InitializationOptions opts1 = { { 6, 9 }, PixelFormat::RGB_565, PixelFormat::RGB_565 }; + std::unique_ptr pixelMap1 = PixelMap::Create(color, sizeof(color) / sizeof(color[0]), opts1); + std::shared_ptr pixelMapIn1 = move(pixelMap1); + pasteDataRecord = pasteDataRecord->NewPixelMapRecord(pixelMapIn1); + ASSERT_TRUE(pasteDataRecord != nullptr); + auto newPixelMap = pasteDataRecord->GetPixelMap(); + ASSERT_TRUE(newPixelMap != nullptr); + ImageInfo imageInfo = {}; + newPixelMap->GetImageInfo(imageInfo); + ASSERT_TRUE(imageInfo.size.height == opts1.size.height); + ASSERT_TRUE(imageInfo.size.width == opts1.size.width); + ASSERT_TRUE(imageInfo.pixelFormat == opts1.pixelFormat); +} + +/** +* @tc.name: PasteRecordTest007 +* @tc.desc: Create paste board record test. +* @tc.type: FUNC +* @tc.require: AR000HEECD +*/ +HWTEST_F(PasteboardServiceTest, PasteRecordTest007, TestSize.Level0) +{ + std::vector arrayBuffer(46); + arrayBuffer = { 2, 7, 6, 8, 9 }; + std::string mimeType = "image/jpg"; + auto pasteDataRecord = PasteboardClient::GetInstance()->CreateKvRecord(mimeType, arrayBuffer); + ASSERT_TRUE(pasteDataRecord != nullptr); + auto customData = pasteDataRecord->GetCustomData(); + ASSERT_TRUE(customData != nullptr); + auto itemData = customData->GetItemData(); + ASSERT_TRUE(itemData.size() == 1); + auto item = itemData.find(mimeType); + ASSERT_TRUE(item != itemData.end()); + ASSERT_TRUE(item->second == arrayBuffer); +} + +/** +* @tc.name: PasteRecordTest008 +* @tc.desc: Create paste board record test. +* @tc.type: FUNC +* @tc.require: AR000HEECD +*/ +HWTEST_F(PasteboardServiceTest, PasteRecordTest008, TestSize.Level0) +{ + std::vector arrayBuffer(46); + arrayBuffer = { 2, 7, 6, 8, 9 }; + std::string mimeType = "image/jpg"; + auto pasteDataRecord = PasteboardClient::GetInstance()->CreateKvRecord(mimeType, arrayBuffer); + ASSERT_TRUE(pasteDataRecord != nullptr); + std::string mimeType1 = "img/png"; + std::vector arrayBuffer1(46); + arrayBuffer1 = { 2, 7, 6, 8, 9 }; + pasteDataRecord = pasteDataRecord->NewKvRecord(mimeType1, arrayBuffer1); + auto customData = pasteDataRecord->GetCustomData(); + ASSERT_TRUE(customData != nullptr); + auto itemData = customData->GetItemData(); + ASSERT_TRUE(itemData.size() == 1); + auto item = itemData.find(mimeType1); + ASSERT_TRUE(item != itemData.end()); + ASSERT_TRUE(item->second == arrayBuffer1); +} + +/** +* @tc.name: PasteRecordTest009 +* @tc.desc: Create paste board html local url +* @tc.type: FUNC +*/ +HWTEST_F(PasteboardServiceTest, PasteRecordTest009, TestSize.Level0) +{ + std::string htmlText = + "
"; + auto data = PasteboardClient::GetInstance()->CreateHtmlData(htmlText); + ASSERT_TRUE(data != nullptr); + data->SetTag(g_webviewPastedataTag); + int32_t ret = PasteboardClient::GetInstance()->SetPasteData(*data); + ASSERT_TRUE(ret == static_cast(PasteboardError::E_OK)); + auto has = PasteboardClient::GetInstance()->HasPasteData(); + ASSERT_TRUE(has == true); + PasteData newPasteData; + ret = PasteboardClient::GetInstance()->GetPasteData(newPasteData); + ASSERT_TRUE(ret == static_cast(PasteboardError::E_OK)); + auto record = newPasteData.GetPrimaryHtml(); + ASSERT_TRUE(record != nullptr); +} + +/** +* @tc.name: PasteRecordTest0010 +* @tc.desc: Create paste board html distributed uri. +* @tc.type: FUNC +*/ +HWTEST_F(PasteboardServiceTest, PasteRecordTest0010, TestSize.Level0) +{ + std::string htmlText = + "
"; + auto data = PasteboardClient::GetInstance()->CreateHtmlData(htmlText); + ASSERT_TRUE(data != nullptr); + data->SetTag(g_webviewPastedataTag); + int32_t ret = PasteboardClient::GetInstance()->SetPasteData(*data); + ASSERT_TRUE(ret == static_cast(PasteboardError::E_OK)); + auto has = PasteboardClient::GetInstance()->HasPasteData(); + ASSERT_TRUE(has == true); + PasteData newPasteData2; + ret = PasteboardClient::GetInstance()->GetPasteData(newPasteData2); + ASSERT_TRUE(ret == static_cast(PasteboardError::E_OK)); + auto record = newPasteData2.GetPrimaryHtml(); + ASSERT_TRUE(record != nullptr); + ASSERT_TRUE(*record == htmlText); +} + +/** +* @tc.name: PasteDataTest001 +* @tc.desc: Create paste board data test. +* @tc.type: FUNC +*/ +HWTEST_F(PasteboardServiceTest, PasteDataTest001, TestSize.Level0) +{ + using namespace OHOS::AAFwk; + std::shared_ptr want = std::make_shared(); + std::string key = "id"; + int32_t id = 456; + Want wantIn = want->SetParam(key, id); + auto data = PasteboardClient::GetInstance()->CreateWantData(std::make_shared(wantIn)); + ASSERT_TRUE(data != nullptr); + PasteboardClient::GetInstance()->Clear(); + auto has = PasteboardClient::GetInstance()->HasPasteData(); + ASSERT_TRUE(has != true); + int32_t ret = PasteboardClient::GetInstance()->SetPasteData(*data); + ASSERT_TRUE(ret == static_cast(PasteboardError::E_OK)); + has = PasteboardClient::GetInstance()->HasPasteData(); + ASSERT_TRUE(has == true); + PasteData pasteData; + ret = PasteboardClient::GetInstance()->GetPasteData(pasteData); + ASSERT_TRUE(ret == static_cast(PasteboardError::E_OK)); + auto record = pasteData.GetPrimaryWant(); + ASSERT_TRUE(record != nullptr); + int32_t defaultValue = 333; + ASSERT_TRUE(record->GetIntParam(key, defaultValue) == id); +} + +/** +* @tc.name: PasteDataTest002 +* @tc.desc: Create paste board data test. +* @tc.type: FUNC +*/ +HWTEST_F(PasteboardServiceTest, PasteDataTest002, TestSize.Level0) +{ + OHOS::Uri uri("uri"); + auto data = PasteboardClient::GetInstance()->CreateUriData(uri); + ASSERT_TRUE(data != nullptr); + PasteboardClient::GetInstance()->Clear(); + auto has = PasteboardClient::GetInstance()->HasPasteData(); + ASSERT_TRUE(has != true); + int32_t ret = PasteboardClient::GetInstance()->SetPasteData(*data); + ASSERT_TRUE(ret == static_cast(PasteboardError::E_OK)); + has = PasteboardClient::GetInstance()->HasPasteData(); + ASSERT_TRUE(has == true); + PasteData pasteData; + ret = PasteboardClient::GetInstance()->GetPasteData(pasteData); + ASSERT_TRUE(ret == static_cast(PasteboardError::E_OK)); + auto record = pasteData.GetPrimaryUri(); + ASSERT_TRUE(record != nullptr); + ASSERT_TRUE(record->ToString() == uri.ToString()); +} + +/** +* @tc.name: PasteDataTest003 +* @tc.desc: Create paste board data test. +* @tc.type: FUNC +*/ +HWTEST_F(PasteboardServiceTest, PasteDataTest003, TestSize.Level0) +{ + std::string text = "plain text"; + auto data = PasteboardClient::GetInstance()->CreatePlainTextData(text); + ASSERT_TRUE(data != nullptr); + PasteboardClient::GetInstance()->Clear(); + auto has = PasteboardClient::GetInstance()->HasPasteData(); + ASSERT_TRUE(has != true); + int32_t ret = PasteboardClient::GetInstance()->SetPasteData(*data); + ASSERT_TRUE(ret == static_cast(PasteboardError::E_OK)); + has = PasteboardClient::GetInstance()->HasPasteData(); + ASSERT_TRUE(has == true); + PasteData pasteData; + ret = PasteboardClient::GetInstance()->GetPasteData(pasteData); + ASSERT_TRUE(ret == static_cast(PasteboardError::E_OK)); + auto record = pasteData.GetPrimaryText(); + ASSERT_TRUE(record != nullptr); + ASSERT_TRUE(*record == text); +} + +/** +* @tc.name: PasteDataTest004 +* @tc.desc: Create paste board data test. +* @tc.type: FUNC +*/ +HWTEST_F(PasteboardServiceTest, PasteDataTest004, TestSize.Level0) +{ + std::string htmlText = "
"; + auto data = PasteboardClient::GetInstance()->CreateHtmlData(htmlText); + ASSERT_TRUE(data != nullptr); + PasteboardClient::GetInstance()->Clear(); + auto has = PasteboardClient::GetInstance()->HasPasteData(); + ASSERT_TRUE(has != true); + int32_t ret = PasteboardClient::GetInstance()->SetPasteData(*data); + ASSERT_TRUE(ret == static_cast(PasteboardError::E_OK)); + has = PasteboardClient::GetInstance()->HasPasteData(); + ASSERT_TRUE(has == true); + PasteData pasteData; + ret = PasteboardClient::GetInstance()->GetPasteData(pasteData); + ASSERT_TRUE(ret == static_cast(PasteboardError::E_OK)); + auto record = pasteData.GetPrimaryHtml(); + ASSERT_TRUE(record != nullptr); + ASSERT_TRUE(*record == htmlText); +} + +/** +* @tc.name: PasteDataTest005 +* @tc.desc: CreateHtmlData test. +* @tc.type: FUNC +* @tc.require: AR000HEECD +*/ +HWTEST_F(PasteboardServiceTest, PasteDataTest005, TestSize.Level0) +{ + std::string htmlText = "
"; + auto pasteData = PasteboardClient::GetInstance()->CreateHtmlData(htmlText); + ASSERT_TRUE(pasteData != nullptr); + std::string plainText = "plain text"; + PasteDataRecord::Builder builder(MIMETYPE_TEXT_HTML); + std::string mimeType = MIMETYPE_TEXT_PLAIN; + std::vector arrayBuffer(46); + arrayBuffer = { 2, 7, 6, 8, 9 }; + std::string mimeType1 = "image/jpg"; + std::shared_ptr customData = std::make_shared(); + customData->AddItemData(mimeType1, arrayBuffer); + std::shared_ptr pasteDataRecord = builder.SetMimeType(mimeType) + .SetPlainText(std::make_shared(plainText)) + .SetHtmlText(std::make_shared(htmlText)) + .SetCustomData(customData) + .Build(); + pasteData->AddRecord(pasteDataRecord); + PasteData newPasteData; + PasteboardServiceTest::CommonTest(*pasteData, newPasteData); + auto primaryHtml = newPasteData.GetPrimaryHtml(); + ASSERT_TRUE(primaryHtml != nullptr); + ASSERT_TRUE(*primaryHtml == htmlText); + auto firstRecord = newPasteData.GetRecordAt(0); + ASSERT_TRUE(firstRecord != nullptr); + ASSERT_TRUE(firstRecord->GetMimeType() == mimeType); + auto newPlainText = firstRecord->GetPlainText(); + ASSERT_TRUE(newPlainText != nullptr); + ASSERT_TRUE(*newPlainText == plainText); + auto newHtmlText = firstRecord->GetHtmlText(); + ASSERT_TRUE(newHtmlText != nullptr); + ASSERT_TRUE(*newHtmlText == htmlText); + customData = pasteDataRecord->GetCustomData(); + ASSERT_TRUE(customData != nullptr); + auto itemData = customData->GetItemData(); + ASSERT_TRUE(itemData.size() == 1); + auto item = itemData.find(mimeType1); + ASSERT_TRUE(item != itemData.end()); + ASSERT_TRUE(item->second == arrayBuffer); +} + +/** +* @tc.name: PasteDataTest006 +* @tc.desc: CreatePlainTextData test. +* @tc.type: FUNC +*/ +HWTEST_F(PasteboardServiceTest, PasteDataTest006, TestSize.Level0) +{ + using namespace OHOS::AAFwk; + std::string plainText = "helloWorld"; + auto pasteData = PasteboardClient::GetInstance()->CreatePlainTextData(plainText); + ASSERT_TRUE(pasteData != nullptr); + std::shared_ptr want = std::make_shared(); + std::string key = "id"; + int32_t id = 456; + Want wantIn = want->SetParam(key, id); + PasteDataRecord::Builder builder(MIMETYPE_TEXT_WANT); + std::shared_ptr pasteDataRecord = + builder.SetWant(std::make_shared(wantIn)).SetPlainText(std::make_shared(plainText)).Build(); + pasteData->AddRecord(pasteDataRecord); + PasteData newPasteData; + PasteboardServiceTest::CommonTest(*pasteData, newPasteData); + auto firstRecord = newPasteData.GetRecordAt(0); + ASSERT_TRUE(firstRecord != nullptr); + ASSERT_TRUE(firstRecord->GetMimeType() == MIMETYPE_TEXT_WANT); + auto newWant = firstRecord->GetWant(); + ASSERT_TRUE(newWant != nullptr); + int32_t defaultValue = 333; + ASSERT_TRUE(newWant->GetIntParam(key, defaultValue) == id); + auto newPlainText = firstRecord->GetPlainText(); + ASSERT_TRUE(newPlainText != nullptr); + ASSERT_TRUE(*newPlainText == plainText); +} + +/** +* @tc.name: PasteDataTest007 +* @tc.desc: PixelMap test. +* @tc.type: FUNC +* @tc.require: AR000H5GKU +*/ +HWTEST_F(PasteboardServiceTest, PasteDataTest007, TestSize.Level0) +{ + std::string htmlText = "
"; + auto pasteData = PasteboardClient::GetInstance()->CreateHtmlData(htmlText); + ASSERT_TRUE(pasteData != nullptr); + OHOS::Uri uri("uri"); + uint32_t color[100] = { 3, 7, 9, 9, 7, 6 }; + InitializationOptions opts = { { 5, 7 }, PixelFormat::ARGB_8888, PixelFormat::ARGB_8888 }; + std::unique_ptr pixelMap = PixelMap::Create(color, sizeof(color) / sizeof(color[0]), opts); + std::shared_ptr pixelMapIn = move(pixelMap); + PasteDataRecord::Builder builder(MIMETYPE_TEXT_URI); + std::shared_ptr pasteDataRecord = + builder.SetUri(std::make_shared(uri)).SetPixelMap(pixelMapIn).Build(); + pasteData->AddRecord(pasteDataRecord); + PasteData newPasteData; + PasteboardServiceTest::CommonTest(*pasteData, newPasteData); + auto firstRecord = newPasteData.GetRecordAt(0); + ASSERT_TRUE(firstRecord != nullptr); + ASSERT_TRUE(firstRecord->GetMimeType() == MIMETYPE_TEXT_URI); + auto newUri = firstRecord->GetUri(); + ASSERT_TRUE(newUri != nullptr); + ASSERT_TRUE(newUri->ToString() == uri.ToString()); + auto newPixelMap = firstRecord->GetPixelMap(); + ASSERT_TRUE(newPixelMap != nullptr); + ImageInfo imageInfo = {}; + newPixelMap->GetImageInfo(imageInfo); + ASSERT_TRUE(imageInfo.size.height == opts.size.height); + ASSERT_TRUE(imageInfo.size.width == opts.size.width); + ASSERT_TRUE(imageInfo.pixelFormat == opts.pixelFormat); +} + +/** +* @tc.name: PasteDataTest008 +* @tc.desc: Create paste board data test. +* @tc.type: FUNC +* @tc.require: AR000H5GKU +*/ +HWTEST_F(PasteboardServiceTest, PasteDataTest008, TestSize.Level0) +{ + uint32_t color[100] = { 3, 7, 9, 9, 7, 6 }; + InitializationOptions opts = { { 5, 7 }, PixelFormat::ARGB_8888, PixelFormat::ARGB_8888 }; + std::unique_ptr pixelMap = PixelMap::Create(color, sizeof(color) / sizeof(color[0]), opts); + std::shared_ptr pixelMapIn = move(pixelMap); + auto pasteData = PasteboardClient::GetInstance()->CreatePixelMapData(pixelMapIn); + ASSERT_TRUE(pasteData != nullptr); + PasteData newPasteData; + PasteboardServiceTest::CommonTest(*pasteData, newPasteData); + auto primaryPixelMap = newPasteData.GetPrimaryPixelMap(); + ASSERT_TRUE(primaryPixelMap != nullptr); + ImageInfo imageInfo = {}; + primaryPixelMap->GetImageInfo(imageInfo); + ASSERT_TRUE(imageInfo.size.height == opts.size.height); + ASSERT_TRUE(imageInfo.size.width == opts.size.width); + ASSERT_TRUE(imageInfo.pixelFormat == opts.pixelFormat); +} + +/** +* @tc.name: PasteDataTest009 +* @tc.desc: Create paste board data test. +* @tc.type: FUNC +* @tc.require: AR000H5GKU +*/ +HWTEST_F(PasteboardServiceTest, PasteDataTest009, TestSize.Level0) +{ + std::string plainText = "plain text"; + auto pasteData = PasteboardClient::GetInstance()->CreatePlainTextData(plainText); + ASSERT_TRUE(pasteData != nullptr); + uint32_t color[100] = { 3, 7, 9, 9, 7, 6 }; + InitializationOptions opts = { { 5, 7 }, PixelFormat::ARGB_8888, PixelFormat::ARGB_8888 }; + std::unique_ptr pixelMap = PixelMap::Create(color, sizeof(color) / sizeof(color[0]), opts); + std::shared_ptr pixelMapIn = move(pixelMap); + pasteData->AddPixelMapRecord(pixelMapIn); + PasteData newPasteData; + PasteboardServiceTest::CommonTest(*pasteData, newPasteData); + auto primaryPlainText = newPasteData.GetPrimaryText(); + ASSERT_TRUE(primaryPlainText != nullptr); + ASSERT_TRUE(*primaryPlainText == plainText); + auto primaryPixelMap = newPasteData.GetPrimaryPixelMap(); + ASSERT_TRUE(primaryPixelMap != nullptr); + ImageInfo imageInfo = {}; + primaryPixelMap->GetImageInfo(imageInfo); + ASSERT_TRUE(imageInfo.size.height == opts.size.height); + ASSERT_TRUE(imageInfo.size.width == opts.size.width); + ASSERT_TRUE(imageInfo.pixelFormat == opts.pixelFormat); +} + +/** +* @tc.name: PasteDataTest0010 +* @tc.desc: Create paste board data test. +* @tc.type: FUNC +* @tc.require: AR000HEECD +*/ +HWTEST_F(PasteboardServiceTest, PasteDataTest0010, TestSize.Level0) +{ + std::vector arrayBuffer(46); + arrayBuffer = { 2, 7, 6, 8, 9 }; + std::string mimeType = "image/jpg"; + auto pasteData = PasteboardClient::GetInstance()->CreateKvData(mimeType, arrayBuffer); + ASSERT_TRUE(pasteData != nullptr); + PasteData newPasteData; + PasteboardServiceTest::CommonTest(*pasteData, newPasteData); + auto firstRecord = newPasteData.GetRecordAt(0); + auto customData = firstRecord->GetCustomData(); + ASSERT_TRUE(customData != nullptr); + auto itemData = customData->GetItemData(); + ASSERT_TRUE(itemData.size() == 1); + auto item = itemData.find(mimeType); + ASSERT_TRUE(item != itemData.end()); + ASSERT_TRUE(item->second == arrayBuffer); +} + +/** +* @tc.name: PasteDataTest0011 +* @tc.desc: Create paste board data test. +* @tc.type: FUNC +* @tc.require: AR000HEECD +*/ +HWTEST_F(PasteboardServiceTest, PasteDataTest0011, TestSize.Level0) +{ + std::string plainText = "plain text"; + auto pasteData = PasteboardClient::GetInstance()->CreatePlainTextData(plainText); + ASSERT_TRUE(pasteData != nullptr); + std::vector arrayBuffer(46); + arrayBuffer = { 2, 7, 6, 8, 9 }; + std::string mimeType = "image/jpg"; + pasteData->AddKvRecord(mimeType, arrayBuffer); + PasteData newPasteData; + PasteboardServiceTest::CommonTest(*pasteData, newPasteData); + auto firstRecord = newPasteData.GetRecordAt(0); + auto customData = firstRecord->GetCustomData(); + ASSERT_TRUE(customData != nullptr); + auto itemData = customData->GetItemData(); + ASSERT_TRUE(itemData.size() == 1); + auto item = itemData.find(mimeType); + ASSERT_TRUE(item != itemData.end()); + ASSERT_TRUE(item->second == arrayBuffer); + auto primaryPlainText = newPasteData.GetPrimaryText(); + ASSERT_TRUE(primaryPlainText != nullptr); + ASSERT_TRUE(*primaryPlainText == plainText); +} + +/** +* @tc.name: PasteDataTest0012 +* @tc.desc: Create paste board data test. +* @tc.type: FUNC +* @tc.require: AR000HEECD +*/ +HWTEST_F(PasteboardServiceTest, PasteDataTest0012, TestSize.Level0) +{ + std::string plainText = "plain text"; + auto pasteData = PasteboardClient::GetInstance()->CreatePlainTextData(plainText); + ASSERT_TRUE(pasteData != nullptr); + std::vector arrayBuffer(46); + arrayBuffer = { 2, 7, 6, 8, 9 }; + std::string mimeType = "image/jpg"; + pasteData->AddKvRecord(mimeType, arrayBuffer); + auto record = pasteData->GetRecordAt(0); + ASSERT_TRUE(record != nullptr); + std::string mimeType1 = "img/png"; + std::vector arrayBuffer1(54); + arrayBuffer1 = { 4, 7, 9, 8, 7 }; + auto customData = record->GetCustomData(); + ASSERT_TRUE(customData != nullptr); + customData->AddItemData(mimeType1, arrayBuffer1); + PasteData newPasteData; + PasteboardServiceTest::CommonTest(*pasteData, newPasteData); + auto firstRecord = newPasteData.GetRecordAt(0); + ASSERT_TRUE(firstRecord != nullptr); + customData = firstRecord->GetCustomData(); + ASSERT_TRUE(customData != nullptr); + auto itemData = customData->GetItemData(); + ASSERT_TRUE(itemData.size() == 2); + auto item = itemData.find(mimeType); + ASSERT_TRUE(item != itemData.end()); + ASSERT_TRUE(item->second == arrayBuffer); + item = itemData.find(mimeType1); + ASSERT_TRUE(item != itemData.end()); + ASSERT_TRUE(item->second == arrayBuffer1); + auto primaryPlainText = newPasteData.GetPrimaryText(); + ASSERT_TRUE(primaryPlainText != nullptr); + ASSERT_TRUE(*primaryPlainText == plainText); + auto secondRecord = newPasteData.GetRecordAt(1); + ASSERT_TRUE(secondRecord != nullptr); + auto secondRecordMimeType = secondRecord->GetMimeType(); + ASSERT_TRUE(secondRecordMimeType == MIMETYPE_TEXT_PLAIN); +} + +/** +* @tc.name: PasteDataTest0014 +* @tc.desc: Create paste board data test. +* @tc.type: FUNC +* @tc.require: AROOOH5R5G +*/ +HWTEST_F(PasteboardServiceTest, PasteDataTest0014, TestSize.Level0) +{ + std::string plainText = "plain text"; + auto pasteData = PasteboardClient::GetInstance()->CreatePlainTextData(plainText); + ASSERT_TRUE(pasteData != nullptr); + auto shareOption = pasteData->GetShareOption(); + ASSERT_TRUE(shareOption == ShareOption::CrossDevice); + pasteData->SetShareOption(ShareOption::InApp); + auto tokenId = pasteData->GetTokenId(); + ASSERT_TRUE(tokenId == 0); + pasteData->SetTokenId(1); + PasteData newPasteData; + PasteboardServiceTest::CommonTest(*pasteData, newPasteData); + shareOption = newPasteData.GetShareOption(); + ASSERT_TRUE(shareOption == ShareOption::InApp); + tokenId = pasteData->GetTokenId(); + ASSERT_TRUE(tokenId != 0); +} + +/** +* @tc.name: PasteDataTest0015 +* @tc.desc: isLocalPaste test. +* @tc.type: FUNC +* @tc.require: AROOOH5R5G +*/ +HWTEST_F(PasteboardServiceTest, PasteDataTest0015, TestSize.Level0) +{ + std::string plainText = "plain text"; + auto pasteData = PasteboardClient::GetInstance()->CreatePlainTextData(plainText); + ASSERT_TRUE(pasteData != nullptr); + auto isLocalPaste = pasteData->IsLocalPaste(); + ASSERT_FALSE(isLocalPaste); + pasteData->SetLocalPasteFlag(true); + isLocalPaste = pasteData->IsLocalPaste(); + ASSERT_TRUE(isLocalPaste); + pasteData->SetLocalPasteFlag(false); + isLocalPaste = pasteData->IsLocalPaste(); + ASSERT_FALSE(isLocalPaste); + PasteboardClient::GetInstance()->Clear(); + auto hasPasteData = PasteboardClient::GetInstance()->HasPasteData(); + ASSERT_FALSE(hasPasteData); + int32_t ret = PasteboardClient::GetInstance()->SetPasteData(*pasteData); + ASSERT_TRUE(ret == static_cast(PasteboardError::E_OK)); + hasPasteData = PasteboardClient::GetInstance()->HasPasteData(); + ASSERT_TRUE(hasPasteData); + PasteData newPasteData; + ret = PasteboardClient::GetInstance()->GetPasteData(newPasteData); + ASSERT_TRUE(ret == static_cast(PasteboardError::E_OK)); + isLocalPaste = newPasteData.IsLocalPaste(); + ASSERT_TRUE(isLocalPaste); +} + +/** +* @tc.name: PasteDataTest0016 +* @tc.desc: RemoveRecordAt HasMimeType test. +* @tc.type: FUNC +* @tc.require: AROOOH5R5G +*/ +HWTEST_F(PasteboardServiceTest, PasteDataTest0016, TestSize.Level0) +{ + std::string plainText = "plain text"; + auto pasteData = PasteboardClient::GetInstance()->CreatePlainTextData(plainText); + ASSERT_TRUE(pasteData != nullptr); + std::vector arrayBuffer(46); + arrayBuffer = { 2, 7, 6, 8, 9 }; + std::string mimeType = "image/jpg"; + pasteData->AddKvRecord(mimeType, arrayBuffer); + pasteData->RemoveRecordAt(1); + PasteboardClient::GetInstance()->Clear(); + auto hasPasteData = PasteboardClient::GetInstance()->HasPasteData(); + ASSERT_FALSE(hasPasteData); + int32_t ret = PasteboardClient::GetInstance()->SetPasteData(*pasteData); + ASSERT_TRUE(ret == static_cast(PasteboardError::E_OK)); + hasPasteData = PasteboardClient::GetInstance()->HasPasteData(); + ASSERT_TRUE(hasPasteData); + PasteData newPasteData; + ret = PasteboardClient::GetInstance()->GetPasteData(newPasteData); + ASSERT_TRUE(ret == static_cast(PasteboardError::E_OK)); + ASSERT_TRUE(newPasteData.HasMimeType(mimeType)); + ASSERT_TRUE(newPasteData.GetRecordCount() == 1); + auto record = newPasteData.GetRecordAt(0); + ASSERT_TRUE(record != nullptr); + auto customData = record->GetCustomData(); + ASSERT_TRUE(customData != nullptr); + auto itemData = customData->GetItemData(); + ASSERT_EQ(itemData.size(), 1); + auto item = itemData.find(mimeType); + ASSERT_TRUE(item != itemData.end()); + EXPECT_EQ(item->second, arrayBuffer); +} + +/** +* @tc.name: PasteDataTest0017 +* @tc.desc: ReplaceRecordAt GetProperty GetTag test. +* @tc.type: FUNC +* @tc.require: AROOOH5R5G +*/ +HWTEST_F(PasteboardServiceTest, PasteDataTest0017, TestSize.Level0) +{ + uint32_t color[100] = { 3, 7, 9, 9, 7, 6 }; + InitializationOptions opts = { { 5, 7 }, PixelFormat::ARGB_8888, PixelFormat::ARGB_8888 }; + std::unique_ptr pixelMap = PixelMap::Create(color, sizeof(color) / sizeof(color[0]), opts); + std::shared_ptr pixelMapIn = move(pixelMap); + auto pasteData = PasteboardClient::GetInstance()->CreatePixelMapData(pixelMapIn); + ASSERT_TRUE(pasteData != nullptr); + auto pixelMap1 = pasteData->GetPrimaryPixelMap(); + ASSERT_TRUE(pixelMap1 != nullptr); + ImageInfo imageInfo = {}; + pixelMap1->GetImageInfo(imageInfo); + ASSERT_EQ(imageInfo.size.height, opts.size.height); + ASSERT_EQ(imageInfo.size.width, opts.size.width); + ASSERT_EQ(imageInfo.pixelFormat, opts.pixelFormat); + std::string plainText = "plain text"; + auto record = PasteboardClient::GetInstance()->CreatePlainTextRecord(plainText); + ASSERT_TRUE(record != nullptr); + ASSERT_TRUE(pasteData->ReplaceRecordAt(0, record)); + PasteboardClient::GetInstance()->Clear(); + auto hasPasteData = PasteboardClient::GetInstance()->HasPasteData(); + ASSERT_FALSE(hasPasteData); + int32_t ret = PasteboardClient::GetInstance()->SetPasteData(*pasteData); + ASSERT_TRUE(ret == static_cast(PasteboardError::E_OK)); + hasPasteData = PasteboardClient::GetInstance()->HasPasteData(); + ASSERT_TRUE(hasPasteData); + PasteData newPasteData; + ret = PasteboardClient::GetInstance()->GetPasteData(newPasteData); + ASSERT_TRUE(ret == static_cast(PasteboardError::E_OK)); + ASSERT_EQ(newPasteData.GetRecordCount(), 1); + auto record1 = newPasteData.GetRecordAt(0); + ASSERT_TRUE(record1 != nullptr); + auto plainText1 = record1->GetPlainText(); + ASSERT_TRUE(plainText1 != nullptr); + EXPECT_EQ(*plainText1, plainText); + auto property = newPasteData.GetProperty(); + EXPECT_TRUE(property.additions.IsEmpty()); + EXPECT_EQ(property.mimeTypes.size(), 1); + EXPECT_EQ(property.mimeTypes[0], MIMETYPE_TEXT_PLAIN); + EXPECT_TRUE(property.tag.empty()); + EXPECT_EQ(property.shareOption, ShareOption::CrossDevice); + EXPECT_TRUE(property.tokenId != 0); + auto tag = newPasteData.GetTag(); + EXPECT_TRUE(tag.empty()); +} + +/** +* @tc.name: PasteDataTest0018 +* @tc.desc: AddPasteboardChangedObserver RemovePasteboardChangedObserver OnRemoteDied OnRemoteSaDied test. +* @tc.type: FUNC +* @tc.require: AROOOH5R5G +*/ +HWTEST_F(PasteboardServiceTest, PasteDataTest0018, TestSize.Level0) +{ + PasteboardClient::GetInstance()->RemovePasteboardChangedObserver(nullptr); + if (PasteboardServiceTest::pasteboardObserver_ == nullptr) { + PasteboardServiceTest::pasteboardObserver_ = new PasteboardObserverCallback(); + } + PasteboardServiceTest::pasteboardChangedFlag_ = false; + ASSERT_TRUE(PasteboardServiceTest::pasteboardObserver_ != nullptr); + PasteboardClient::GetInstance()->AddPasteboardChangedObserver(PasteboardServiceTest::pasteboardObserver_); + ASSERT_FALSE(PasteboardServiceTest::pasteboardChangedFlag_); + const wptr object; + PasteboardSaDeathRecipient death; + death.OnRemoteDied(object); + PasteboardClient::GetInstance()->OnRemoteSaDied(object); + uint32_t color[100] = { 3, 7, 9, 9, 7, 6 }; + InitializationOptions opts = { { 5, 7 }, PixelFormat::ARGB_8888, PixelFormat::ARGB_8888 }; + std::unique_ptr pixelMap = PixelMap::Create(color, sizeof(color) / sizeof(color[0]), opts); + std::shared_ptr pixelMapIn = move(pixelMap); + auto pasteData = PasteboardClient::GetInstance()->CreatePixelMapData(pixelMapIn); + ASSERT_TRUE(pasteData != nullptr); + PasteboardClient::GetInstance()->Clear(); + std::this_thread::sleep_for(std::chrono::milliseconds(5)); + ASSERT_FALSE(PasteboardServiceTest::pasteboardChangedFlag_); + auto hasPasteData = PasteboardClient::GetInstance()->HasPasteData(); + ASSERT_FALSE(hasPasteData); + int32_t ret = PasteboardClient::GetInstance()->SetPasteData(*pasteData); + ASSERT_TRUE(ret == static_cast(PasteboardError::E_OK)); + std::this_thread::sleep_for(std::chrono::milliseconds(5)); + ASSERT_TRUE(PasteboardServiceTest::pasteboardChangedFlag_); + hasPasteData = PasteboardClient::GetInstance()->HasPasteData(); + ASSERT_TRUE(hasPasteData); + PasteData newPasteData; + ret = PasteboardClient::GetInstance()->GetPasteData(newPasteData); + ASSERT_TRUE(ret == static_cast(PasteboardError::E_OK)); + PasteboardServiceTest::pasteboardChangedFlag_ = false; + PasteboardClient::GetInstance()->RemovePasteboardChangedObserver(PasteboardServiceTest::pasteboardObserver_); + PasteboardClient::GetInstance()->Clear(); + ASSERT_FALSE(PasteboardServiceTest::pasteboardChangedFlag_); + hasPasteData = PasteboardClient::GetInstance()->HasPasteData(); + ASSERT_FALSE(hasPasteData); + PasteboardClient::GetInstance()->SetPasteData(*pasteData); + std::this_thread::sleep_for(std::chrono::milliseconds(5)); + ASSERT_FALSE(PasteboardServiceTest::pasteboardChangedFlag_); + hasPasteData = PasteboardClient::GetInstance()->HasPasteData(); + ASSERT_TRUE(hasPasteData); +} + + +/** + * @tc.name: PasteDataTest0019 + * @tc.desc: AddPasteboardEventObserver RemovePasteboardEventObserver test. + * @tc.type: FUNC + * @tc.require: AROOOH5R5G + */ +HWTEST_F(PasteboardServiceTest, PasteDataTest0019, TestSize.Level0) +{ + PasteboardClient::GetInstance()->RemovePasteboardEventObserver(nullptr); + if (PasteboardServiceTest::pasteboardEventObserver_ == nullptr) { + PasteboardServiceTest::pasteboardEventObserver_ = new PasteboardEventObserverCallback(); + } + PasteboardServiceTest::pasteboardEventStatus_ = -1; + ASSERT_TRUE(PasteboardServiceTest::pasteboardEventObserver_ != nullptr); + PasteboardClient::GetInstance()->AddPasteboardEventObserver(PasteboardServiceTest::pasteboardEventObserver_); + ASSERT_EQ(PasteboardServiceTest::pasteboardEventStatus_, -1); + auto pasteData = PasteboardClient::GetInstance()->CreatePlainTextData("hello"); + ASSERT_TRUE(pasteData != nullptr); + PasteboardClient::GetInstance()->Clear(); + ASSERT_EQ(PasteboardServiceTest::pasteboardEventStatus_, -1); + auto hasPasteData = PasteboardClient::GetInstance()->HasPasteData(); + ASSERT_FALSE(hasPasteData); + int32_t ret = PasteboardClient::GetInstance()->SetPasteData(*pasteData); + ASSERT_TRUE(ret == static_cast(PasteboardError::E_OK)); + std::this_thread::sleep_for(std::chrono::milliseconds(5)); + ASSERT_EQ(PasteboardServiceTest::pasteboardEventStatus_, -1); + hasPasteData = PasteboardClient::GetInstance()->HasPasteData(); + ASSERT_TRUE(hasPasteData); + PasteData newPasteData; + ret = PasteboardClient::GetInstance()->GetPasteData(newPasteData); + ASSERT_TRUE(ret == static_cast(PasteboardError::E_OK)); + std::this_thread::sleep_for(std::chrono::milliseconds(5)); + ASSERT_EQ(PasteboardServiceTest::pasteboardEventStatus_, -1); + PasteboardClient::GetInstance()->Clear(); + std::this_thread::sleep_for(std::chrono::milliseconds(5)); + ASSERT_TRUE(ret == static_cast(PasteboardError::E_OK)); + ASSERT_EQ(PasteboardServiceTest::pasteboardEventStatus_, -1); + PasteboardServiceTest::pasteboardEventStatus_ = -1; + PasteboardClient::GetInstance()->RemovePasteboardEventObserver(PasteboardServiceTest::pasteboardEventObserver_); + PasteboardClient::GetInstance()->Clear(); + std::this_thread::sleep_for(std::chrono::milliseconds(5)); + ASSERT_EQ(PasteboardServiceTest::pasteboardEventStatus_, -1); + PasteboardClient::GetInstance()->SetPasteData(*pasteData); + ASSERT_EQ(PasteboardServiceTest::pasteboardEventStatus_, -1); +} + +/** +* @tc.name: PasteDataTest0020 +* @tc.desc: Create paste board test set bundleName and time. +* @tc.type: FUNC +*/ +HWTEST_F(PasteboardServiceTest, PasteDataTest0020, TestSize.Level0) +{ + std::string text = "plain text"; + auto pasteData = PasteboardClient::GetInstance()->CreatePlainTextData(text); + ASSERT_TRUE(pasteData != nullptr); + std::string bundleName = "ohos.acts.distributeddatamgr.pasteboard"; + pasteData->SetBundleName(bundleName); + std::string time = GetTime(); + pasteData->SetTime(time); + int32_t ret = PasteboardClient::GetInstance()->SetPasteData(*pasteData); + ASSERT_TRUE(ret == static_cast(PasteboardError::E_OK)); + auto has = PasteboardClient::GetInstance()->HasPasteData(); + ASSERT_TRUE(has == true); +} + +/** +* @tc.name: PasteDataTest0021 +* @tc.desc: AddPasteboardEventObserver RemovePasteboardEventObserver test. +* @tc.type: FUNC +*/ +HWTEST_F(PasteboardServiceTest, PasteDataTest0021, TestSize.Level0) +{ + PasteboardClient::GetInstance()->AddPasteboardEventObserver(new PasteboardEventObserverCallback()); + PasteboardClient::GetInstance()->AddPasteboardEventObserver(new PasteboardEventObserverCallback()); + PasteboardClient::GetInstance()->AddPasteboardEventObserver(new PasteboardEventObserverCallback()); + auto pasteData = PasteboardClient::GetInstance()->CreatePlainTextData("hello"); + ASSERT_TRUE(pasteData != nullptr); + int32_t ret = PasteboardClient::GetInstance()->SetPasteData(*pasteData); + ASSERT_TRUE(ret == static_cast(PasteboardError::E_OK)); + auto hasData = PasteboardClient::GetInstance()->HasPasteData(); + ASSERT_TRUE(hasData == true); + PasteData newPasteData; + PasteboardClient::GetInstance()->GetPasteData(newPasteData); + PasteboardClient::GetInstance()->Clear(); + std::this_thread::sleep_for(std::chrono::milliseconds(5)); + PasteboardClient::GetInstance()->RemovePasteboardEventObserver(nullptr); + hasData = PasteboardClient::GetInstance()->HasPasteData(); + ASSERT_TRUE(hasData == false); +} + +/** +* @tc.name: PasteDataTest0022 +* @tc.desc: isDraggedData test. +* @tc.type: FUNC +* @tc.require: AROOOH5R5G +*/ +HWTEST_F(PasteboardServiceTest, PasteDataTest0022, TestSize.Level0) +{ + std::string plainText = "plain text"; + auto pasteData = PasteboardClient::GetInstance()->CreatePlainTextData(plainText); + ASSERT_TRUE(pasteData != nullptr); + auto isDraggedData = pasteData->IsDraggedData(); + ASSERT_FALSE(isDraggedData); + pasteData->SetDraggedDataFlag(true); + ASSERT_TRUE(pasteData->IsDraggedData()); + PasteboardClient::GetInstance()->Clear(); + auto hasPasteData = PasteboardClient::GetInstance()->HasPasteData(); + ASSERT_FALSE(hasPasteData); + int32_t ret = PasteboardClient::GetInstance()->SetPasteData(*pasteData); + ASSERT_TRUE(ret == static_cast(PasteboardError::E_OK)); + hasPasteData = PasteboardClient::GetInstance()->HasPasteData(); + ASSERT_FALSE(hasPasteData); + PasteData newPasteData; + ret = PasteboardClient::GetInstance()->GetPasteData(newPasteData); + ASSERT_FALSE(ret == static_cast(PasteboardError::E_OK)); + isDraggedData = newPasteData.IsDraggedData(); + ASSERT_FALSE(isDraggedData); +} + +/** +* @tc.name: BigPixelMap001 +* @tc.desc: paste big pixel map image +* @tc.type: FUNC +* @tc.require:AR000H5I1D +* @tc.author: baoyayong +*/ +HWTEST_F(PasteboardServiceTest, BigPixelMap001, TestSize.Level1) +{ + constexpr uint32_t COLOR_SIZE = 1024 * 1960; + auto color = std::make_unique(COLOR_SIZE); + InitializationOptions opts = { { 1024, 1960 }, PixelFormat::ARGB_8888, PixelFormat::ARGB_8888 }; + std::unique_ptr pixelMap = PixelMap::Create(color.get(), COLOR_SIZE, opts); + auto pasteData1 = PasteboardClient::GetInstance()->CreatePixelMapData(std::move(pixelMap)); + PasteboardClient::GetInstance()->Clear(); + auto hasPasteData = PasteboardClient::GetInstance()->HasPasteData(); + ASSERT_FALSE(hasPasteData); + int32_t ret = PasteboardClient::GetInstance()->SetPasteData(*pasteData1); + ASSERT_TRUE(ret == static_cast(PasteboardError::E_OK)); + hasPasteData = PasteboardClient::GetInstance()->HasPasteData(); + ASSERT_TRUE(hasPasteData); + PasteData pasteData2; + ret = PasteboardClient::GetInstance()->GetPasteData(pasteData2); + ASSERT_TRUE(ret == static_cast(PasteboardError::E_OK)); + auto pixelMap2 = pasteData2.GetPrimaryPixelMap(); + ASSERT_TRUE(pixelMap2 != nullptr); + ImageInfo imageInfo{}; + pixelMap2->GetImageInfo(imageInfo); + EXPECT_TRUE(imageInfo.size.height == opts.size.height); + EXPECT_TRUE(imageInfo.size.width == opts.size.width); + EXPECT_TRUE(imageInfo.pixelFormat == opts.pixelFormat); +} + +/** +* @tc.name: GetPastedataFail001 +* @tc.desc: get paste data fail - SetValue() +* @tc.type: FUNC +* @tc.require: issuesI5WPTM +* @tc.author: chenyu +*/ +HWTEST_F(PasteboardServiceTest, GetPastedataFail001, TestSize.Level1) +{ + PasteboardClient::GetInstance()->Clear(); + PasteData data; + auto ret = PasteboardClient::GetInstance()->GetPasteData(data); + EXPECT_TRUE(ret == static_cast(PasteboardError::E_ERROR)); +} + +/** +* @tc.name: DumpDataTest001 +* @tc.desc: DumpData()-remote, CrossDevice +* @tc.type: FUNC +* @tc.require: issueshI5YDEV +* @tc.author: chenyu +*/ +HWTEST_F(PasteboardServiceTest, DumpDataTest001, TestSize.Level1) +{ + PasteboardServiceTest::SetTestTokenId(); + std::string plainText = "plain text"; + auto pasteData = PasteboardClient::GetInstance()->CreatePlainTextData(plainText); + pasteData->SetRemote(true); + pasteData->SetShareOption(ShareOption::CrossDevice); + PasteboardClient::GetInstance()->Clear(); + int32_t ret = PasteboardClient::GetInstance()->SetPasteData(*pasteData); + EXPECT_TRUE(ret == static_cast(PasteboardError::E_OK)); + std::string result; + ret = PasteboardServiceTest::ExecuteCmd(result); + EXPECT_TRUE(ret); + EXPECT_TRUE(result.find("CrossDevice") != std::string::npos); + EXPECT_TRUE(result.find("remote") != std::string::npos); + PasteboardClient::GetInstance()->Clear(); + PasteboardServiceTest::RestoreSelfTokenId(); +} + +/** +* @tc.name: DumpDataTest002 +* @tc.desc: DumpData()-local, LocalDevice +* @tc.type: FUNC +* @tc.require: issueshI5YDEV +* @tc.author: chenyu +*/ +HWTEST_F(PasteboardServiceTest, DumpDataTest002, TestSize.Level1) +{ + PasteboardServiceTest::SetTestTokenId(); + std::string plainText = "plain text"; + auto pasteData = PasteboardClient::GetInstance()->CreatePlainTextData(plainText); + pasteData->SetShareOption(ShareOption::LocalDevice); + PasteboardClient::GetInstance()->Clear(); + int32_t ret = PasteboardClient::GetInstance()->SetPasteData(*pasteData); + EXPECT_TRUE(ret == static_cast(PasteboardError::E_OK)); + std::string result; + ret = PasteboardServiceTest::ExecuteCmd(result); + EXPECT_TRUE(ret); + EXPECT_TRUE(result.find("LocalDevice") != std::string::npos); + EXPECT_TRUE(result.find("local") != std::string::npos); + PasteboardClient::GetInstance()->Clear(); + PasteboardServiceTest::RestoreSelfTokenId(); +} + +/** +* @tc.name: DumpDataTest003 +* @tc.desc: DumpData()-local, InApp +* @tc.type: FUNC +* @tc.require: issueshI5YDEV +* @tc.author: chenyu +*/ +HWTEST_F(PasteboardServiceTest, DumpDataTest003, TestSize.Level1) +{ + PasteboardServiceTest::SetTestTokenId(); + std::string plainText = "plain text"; + auto pasteData = PasteboardClient::GetInstance()->CreatePlainTextData(plainText); + pasteData->SetShareOption(ShareOption::InApp); + PasteboardClient::GetInstance()->Clear(); + int32_t ret = PasteboardClient::GetInstance()->SetPasteData(*pasteData); + EXPECT_TRUE(ret == static_cast(PasteboardError::E_OK)); + std::string result; + ret = PasteboardServiceTest::ExecuteCmd(result); + EXPECT_TRUE(ret); + EXPECT_TRUE(result.find("InAPP") != std::string::npos); + EXPECT_TRUE(result.find("local") != std::string::npos); + PasteboardClient::GetInstance()->Clear(); + PasteboardServiceTest::RestoreSelfTokenId(); +} + +/** +* @tc.name: DumpDataTest004 +* @tc.desc: DumpData()-no data +* @tc.type: FUNC +* @tc.require: issueshI5YDEV +* @tc.author: chenyu +*/ +HWTEST_F(PasteboardServiceTest, DumpDataTest004, TestSize.Level1) +{ + PasteboardServiceTest::SetTestTokenId(); + PasteboardClient::GetInstance()->Clear(); + + std::string result; + auto ret = PasteboardServiceTest::ExecuteCmd(result); + EXPECT_TRUE(ret); + EXPECT_EQ(result.find("Share"), std::string::npos); + EXPECT_EQ(result.find("Option"), std::string::npos); + PasteboardServiceTest::RestoreSelfTokenId(); +} + +/** +* @tc.name: HasPastePermissionTest001 +* @tc.desc: if (!pasteData->IsDraggedData() && (!isFocusedApp && !IsDefaultIME(GetAppInfo(tokenId)))) +* @tc.type: FUNC +* @tc.require: issueshI5YDEV +* @tc.author: chenyu +*/ +HWTEST_F(PasteboardServiceTest, HasPastePermissionTest001, TestSize.Level0) +{ + PasteboardServiceTest::SetTestTokenId(); + std::vector arrayBuffer(46); + arrayBuffer = { 2, 7, 6, 8, 9 }; + std::string mimeType = "image/jpg"; + auto pasteData = PasteboardClient::GetInstance()->CreateKvData(mimeType, arrayBuffer); + PasteboardClient::GetInstance()->Clear(); + int32_t ret = PasteboardClient::GetInstance()->SetPasteData(*pasteData); + EXPECT_TRUE(ret == static_cast(PasteboardError::E_OK)); + auto hasPasteData = PasteboardClient::GetInstance()->HasPasteData(); + // not DraggedData, not DefaultIME, not FocusedApp + EXPECT_FALSE(hasPasteData); + PasteboardClient::GetInstance()->Clear(); + PasteboardServiceTest::RestoreSelfTokenId(); +} +} // namespace OHOS::MiscServices \ No newline at end of file diff --git a/pasteboard/services/zidl/include/pasteboard_observer_proxy.h b/pasteboard/services/zidl/include/pasteboard_observer_proxy.h new file mode 100644 index 00000000..3299ad44 --- /dev/null +++ b/pasteboard/services/zidl/include/pasteboard_observer_proxy.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef PASTE_BOARD_OBERVER_PROXY_H +#define PASTE_BOARD_OBERVER_PROXY_H + +#include + +#include "i_pasteboard_observer.h" +#include "iremote_broker.h" +#include "iremote_object.h" +#include "iremote_proxy.h" +#include "nocopyable.h" +#include "refbase.h" + +namespace OHOS { +namespace MiscServices { +class PasteboardObserverProxy : public IRemoteProxy { +public: + explicit PasteboardObserverProxy(const sptr &object); + ~PasteboardObserverProxy() = default; + DISALLOW_COPY_AND_MOVE(PasteboardObserverProxy); + void OnPasteboardChanged() override; + void OnPasteboardEvent(std::string bundleName, int32_t status) override; +private: + static inline BrokerDelegator delegator_; +}; +} // namespace MiscServices +} // namespace OHOS +#endif // PASTE_BOARD_OBERVER_PROXY_H diff --git a/pasteboard/services/zidl/include/pasteboard_observer_stub.h b/pasteboard/services/zidl/include/pasteboard_observer_stub.h new file mode 100644 index 00000000..325cec16 --- /dev/null +++ b/pasteboard/services/zidl/include/pasteboard_observer_stub.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PASTE_BOARD_OBERVER_STUB_H +#define PASTE_BOARD_OBERVER_STUB_H + +#include + +#include "i_pasteboard_service.h" +#include "ipc_skeleton.h" +#include "iremote_stub.h" + +namespace OHOS { +namespace MiscServices { +class PasteboardObserverStub : public IRemoteStub { +public: + PasteboardObserverStub(); + ~PasteboardObserverStub(); + int32_t OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override; + +private: + using PasteboardObserverFunc = int32_t (PasteboardObserverStub::*)(MessageParcel &data, MessageParcel &reply); + + virtual int32_t OnPasteboardChangedStub(MessageParcel &data, MessageParcel &reply); + virtual int32_t OnPasteboardEventStub(MessageParcel &data, MessageParcel &reply); + std::map memberFuncMap_; +}; +} // namespace MiscServices +} // namespace OHOS +#endif // PASTE_BOARD_OBERVER_STUB_H diff --git a/pasteboard/services/zidl/include/pasteboard_service_proxy.h b/pasteboard/services/zidl/include/pasteboard_service_proxy.h new file mode 100644 index 00000000..ec8ed4fa --- /dev/null +++ b/pasteboard/services/zidl/include/pasteboard_service_proxy.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2021-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PASTE_BOARD_SERVICE_PROXY_H +#define PASTE_BOARD_SERVICE_PROXY_H + +#include "i_pasteboard_observer.h" +#include "i_pasteboard_service.h" +#include "iremote_proxy.h" + +namespace OHOS { +namespace MiscServices { +class PasteboardServiceProxy : public IRemoteProxy { +public: + explicit PasteboardServiceProxy(const sptr &object); + ~PasteboardServiceProxy() = default; + DISALLOW_COPY_AND_MOVE(PasteboardServiceProxy); + virtual void Clear() override; + virtual int32_t GetPasteData(PasteData &data) override; + virtual bool HasPasteData() override; + virtual int32_t SetPasteData(PasteData &pasteData) override; + virtual bool IsRemoteData() override; + virtual int32_t GetDataSource(std::string &bundleName) override; + virtual bool HasDataType(const std::string &mimeType) override; + virtual void AddPasteboardChangedObserver(const sptr &observer) override; + virtual void RemovePasteboardChangedObserver(const sptr &observer) override; + virtual void RemoveAllChangedObserver() override; + virtual void AddPasteboardEventObserver(const sptr &observer) override; + virtual void RemovePasteboardEventObserver(const sptr &observer) override; + virtual void RemoveAllEventObserver() override; + +private: + static inline BrokerDelegator delegator_; + void ProcessObserver(uint32_t code, const sptr &observer); +}; +} // namespace MiscServices +} // namespace OHOS +#endif // PASTE_BOARD_SERVICE_PROXY_H \ No newline at end of file diff --git a/pasteboard/services/zidl/include/pasteboard_service_stub.h b/pasteboard/services/zidl/include/pasteboard_service_stub.h new file mode 100644 index 00000000..1d5ece45 --- /dev/null +++ b/pasteboard/services/zidl/include/pasteboard_service_stub.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2021-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PASTE_BOARD_SERVICE_STUB_H +#define PASTE_BOARD_SERVICE_STUB_H + +#include +#include + +#include "i_pasteboard_service.h" +#include "ipc_skeleton.h" +#include "iremote_stub.h" + +namespace OHOS { +namespace MiscServices { +class PasteboardServiceStub : public IRemoteStub { +public: + PasteboardServiceStub(); + ~PasteboardServiceStub(); + API_EXPORT int32_t OnRemoteRequest( + uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override; + +private: + using PasteboardServiceFunc = int32_t (PasteboardServiceStub::*)(MessageParcel &data, MessageParcel &reply); + virtual int32_t SavePasteData(std::shared_ptr &pasteData) = 0; + int32_t OnClear(MessageParcel &data, MessageParcel &reply); + int32_t OnGetPasteData(MessageParcel &data, MessageParcel &reply); + int32_t OnHasPasteData(MessageParcel &data, MessageParcel &reply); + int32_t OnSetPasteData(MessageParcel &data, MessageParcel &reply); + int32_t OnAddPasteboardChangedObserver(MessageParcel &data, MessageParcel &reply); + int32_t OnRemovePasteboardChangedObserver(MessageParcel &data, MessageParcel &reply); + int32_t OnRemoveAllChangedObserver(MessageParcel &data, MessageParcel &reply); + int32_t OnAddPasteboardEventObserver(MessageParcel &data, MessageParcel &reply); + int32_t OnRemovePasteboardEventObserver(MessageParcel &data, MessageParcel &reply); + int32_t OnRemoveAllEventObserver(MessageParcel &data, MessageParcel &reply); + int32_t OnIsRemoteData(MessageParcel &data, MessageParcel &reply); + int32_t OnGetDataSource(MessageParcel &data, MessageParcel &reply); + int32_t OnHasDataType(MessageParcel &data, MessageParcel &reply); + inline bool IsObserverValid(MessageParcel &data, sptr &callback); + + std::map memberFuncMap_; + static constexpr uint32_t MAX_BUNDLE_NAME_LENGTH = 127; +}; +} // namespace MiscServices +} // namespace OHOS + +#endif // PASTE_BOARD_SERVICE_STUB_H \ No newline at end of file diff --git a/pasteboard/services/zidl/src/pasteboard_observer_proxy.cpp b/pasteboard/services/zidl/src/pasteboard_observer_proxy.cpp new file mode 100644 index 00000000..ae880ae0 --- /dev/null +++ b/pasteboard/services/zidl/src/pasteboard_observer_proxy.cpp @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "pasteboard_observer_proxy.h" + +#include "errors.h" +#include "message_option.h" +#include "message_parcel.h" +#include "pasteboard_hilog.h" +#include "pasteboard_serv_ipc_interface_code.h" + +using namespace OHOS::Security::PasteboardServ; +namespace OHOS { +namespace MiscServices { +PasteboardObserverProxy::PasteboardObserverProxy(const sptr &object) + : IRemoteProxy(object) +{ +} + +void PasteboardObserverProxy::OnPasteboardChanged() +{ + MessageParcel data; + MessageParcel reply; + MessageOption option = { MessageOption::TF_ASYNC }; + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "start."); + if (!data.WriteInterfaceToken(GetDescriptor())) { + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "write descriptor failed!"); + return; + } + + int ret = Remote()->SendRequest( + static_cast(PasteboardObserverInterfaceCode::ON_PASTE_BOARD_CHANGE), data, reply, option); + if (ret != ERR_OK) { + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "SendRequest is failed, error code: %{public}d", ret); + } + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "end."); + return; +} + +void PasteboardObserverProxy::OnPasteboardEvent(std::string bundleName, int32_t status) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option = { MessageOption::TF_ASYNC }; + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "start."); + if (!data.WriteInterfaceToken(GetDescriptor())) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "write descriptor failed!"); + return; + } + data.WriteString(bundleName); + data.WriteInt32(status); + int ret = Remote()->SendRequest( + static_cast(PasteboardObserverInterfaceCode::ON_PASTE_BOARD_EVENT), data, reply, option); + if (ret != ERR_OK) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "SendRequest is failed, error code: %{public}d", ret); + } + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "end."); + return; +} +} // namespace MiscServices +} // namespace OHOS diff --git a/pasteboard/services/zidl/src/pasteboard_observer_stub.cpp b/pasteboard/services/zidl/src/pasteboard_observer_stub.cpp new file mode 100644 index 00000000..cb145564 --- /dev/null +++ b/pasteboard/services/zidl/src/pasteboard_observer_stub.cpp @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "pasteboard_observer_stub.h" + +#include "i_pasteboard_observer.h" +#include "pasteboard_error.h" +#include "pasteboard_serv_ipc_interface_code.h" + +using namespace OHOS::Security::PasteboardServ; +namespace OHOS { +namespace MiscServices { +PasteboardObserverStub::PasteboardObserverStub() +{ + memberFuncMap_[static_cast(PasteboardObserverInterfaceCode::ON_PASTE_BOARD_CHANGE)] = + &PasteboardObserverStub::OnPasteboardChangedStub; + memberFuncMap_[static_cast(PasteboardObserverInterfaceCode::ON_PASTE_BOARD_EVENT)] = + &PasteboardObserverStub::OnPasteboardEventStub; +} + +int32_t PasteboardObserverStub::OnRemoteRequest( + uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) +{ + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "start##code = %{public}u", code); + std::u16string myDescripter = PasteboardObserverStub::GetDescriptor(); + std::u16string remoteDescripter = data.ReadInterfaceToken(); + if (myDescripter != remoteDescripter) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "end##descriptor checked fail"); + return IPCObjectStub::OnRemoteRequest(code, data, reply, option); + } + pid_t p = IPCSkeleton::GetCallingPid(); + pid_t p1 = IPCSkeleton::GetCallingUid(); + PASTEBOARD_HILOGI( + PASTEBOARD_MODULE_SERVICE, "CallingPid = %{public}d, CallingUid = %{public}d, code = %{public}u", p, p1, code); + auto itFunc = memberFuncMap_.find(code); + if (itFunc != memberFuncMap_.end()) { + auto memberFunc = itFunc->second; + if (memberFunc != nullptr) { + return (this->*memberFunc)(data, reply); + } + } + int ret = IPCObjectStub::OnRemoteRequest(code, data, reply, option); + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "end##ret = %{public}d", ret); + return ret; +} + +int32_t PasteboardObserverStub::OnPasteboardChangedStub(MessageParcel &data, MessageParcel &reply) +{ + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "start."); + OnPasteboardChanged(); + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "end."); + return ERR_OK; +} + +int32_t PasteboardObserverStub::OnPasteboardEventStub(MessageParcel &data, MessageParcel &reply) +{ + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "start."); + std::string bundleName = data.ReadString(); + int32_t status = data.ReadInt32(); + OnPasteboardEvent(bundleName, status); + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "end."); + return ERR_OK; +} + +PasteboardObserverStub::~PasteboardObserverStub() +{ + memberFuncMap_.clear(); +} +} // namespace MiscServices +} // namespace OHOS diff --git a/pasteboard/services/zidl/src/pasteboard_service_proxy.cpp b/pasteboard/services/zidl/src/pasteboard_service_proxy.cpp new file mode 100644 index 00000000..3096c75a --- /dev/null +++ b/pasteboard/services/zidl/src/pasteboard_service_proxy.cpp @@ -0,0 +1,301 @@ +/* + * Copyright (C) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is: distributed on an "AS is:"BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "pasteboard_service_proxy.h" + +#include "copy_uri_handler.h" +#include "iremote_broker.h" +#include "paste_uri_handler.h" +#include "pasteboard_error.h" +#include "pasteboard_hilog.h" +#include "pasteboard_serv_ipc_interface_code.h" + +using namespace OHOS::Security::PasteboardServ; +namespace OHOS { +namespace MiscServices { +PasteboardServiceProxy::PasteboardServiceProxy(const sptr &object) + : IRemoteProxy(object) +{ +} + +void PasteboardServiceProxy::Clear() +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "start."); + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "Failed to write parcelable"); + return; + } + + int32_t result = Remote()->SendRequest(PasteboardServiceInterfaceCode::CLEAR_ALL, data, reply, option); + if (result != ERR_NONE) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "failed, error code is: %{public}d", result); + } +} + +bool PasteboardServiceProxy::HasPasteData() +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "start."); + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!data.WriteInterfaceToken(GetDescriptor())) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "Failed to write parcelable"); + return false; + } + + int32_t result = Remote()->SendRequest(PasteboardServiceInterfaceCode::HAS_PASTE_DATA, data, reply, option); + if (result != ERR_NONE) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "failed, error code is: %{public}d", result); + return false; + } + auto has = reply.ReadBool(); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "end."); + return has; +} + +int32_t PasteboardServiceProxy::SetPasteData(PasteData &pasteData) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "start."); + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "Failed to write parcelable"); + return ERR_INVALID_VALUE; + } + std::vector pasteDataTlv(0); + bool ret = pasteData.Encode(pasteDataTlv); + if (!ret) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "Failed to encode pastedata in TLV"); + return ERR_INVALID_VALUE; + } + if (!data.WriteInt32(pasteDataTlv.size())) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "Failed to write raw size"); + return ERR_INVALID_VALUE; + } + if (!data.WriteRawData(pasteDataTlv.data(), pasteDataTlv.size())) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "Failed to write raw data"); + return ERR_INVALID_VALUE; + } + CopyUriHandler copyHandler; + if (!pasteData.WriteUriFd(data, copyHandler)) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "Failed to write record uri fd"); + return ERR_INVALID_VALUE; + } + + int32_t result = Remote()->SendRequest(PasteboardServiceInterfaceCode::SET_PASTE_DATA, data, reply, option); + if (result != ERR_NONE) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "failed, error code is: %{public}d", result); + return ERR_INVALID_OPERATION; + } + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "end."); + return reply.ReadInt32(); +} + +int32_t PasteboardServiceProxy::GetPasteData(PasteData &pasteData) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "start."); + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "Failed to write parcelable"); + return ERR_INVALID_VALUE; + } + int32_t result = Remote()->SendRequest(PasteboardServiceInterfaceCode::GET_PASTE_DATA, data, reply, option); + if (result != ERR_NONE) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "failed, error code is: %{public}d", result); + return ERR_INVALID_OPERATION; + } + int32_t rawDataSize = reply.ReadInt32(); + if (rawDataSize <= 0) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "Failed to get raw size"); + return ERR_INVALID_VALUE; + } + auto *rawData = (uint8_t *)reply.ReadRawData(rawDataSize); + if (rawData == nullptr) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "Failed to get raw data"); + return ERR_INVALID_VALUE; + } + std::vector pasteDataTlv(rawData, rawData + rawDataSize); + bool ret = pasteData.Decode(pasteDataTlv); + if (!ret) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "Failed to decode pastedata in TLV"); + return ERR_INVALID_VALUE; + } + PasteUriHandler pasteHandler; + if (!pasteData.ReadUriFd(reply, pasteHandler)) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "Failed to write record uri fd"); + return ERR_INVALID_VALUE; + } + + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "end."); + return reply.ReadInt32(); +} + +void PasteboardServiceProxy::AddPasteboardChangedObserver(const sptr &observer) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "start."); + ProcessObserver(PasteboardServiceInterfaceCode::ADD_CHANGED_OBSERVER, observer); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "end."); +} + +void PasteboardServiceProxy::RemovePasteboardChangedObserver(const sptr &observer) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "start."); + ProcessObserver(PasteboardServiceInterfaceCode::DELETE_CHANGED_OBSERVER, observer); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "end."); +} +void PasteboardServiceProxy::RemoveAllChangedObserver() +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "start."); + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "Failed to write parcelable"); + return; + } + int32_t result = + Remote()->SendRequest(PasteboardServiceInterfaceCode::DELETE_ALL_CHANGED_OBSERVER, data, reply, option); + if (result != ERR_NONE) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "failed, error code is: %{public}d", result); + } + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "end."); +} + +void PasteboardServiceProxy::AddPasteboardEventObserver(const sptr &observer) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "start."); + ProcessObserver(PasteboardServiceInterfaceCode::ADD_EVENT_OBSERVER, observer); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "end."); +} + +void PasteboardServiceProxy::RemovePasteboardEventObserver(const sptr &observer) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "start."); + ProcessObserver(PasteboardServiceInterfaceCode::DELETE_EVENT_OBSERVER, observer); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "end."); +} +void PasteboardServiceProxy::RemoveAllEventObserver() +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "start."); + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "Failed to write parcelable"); + return; + } + int32_t result = + Remote()->SendRequest(PasteboardServiceInterfaceCode::DELETE_ALL_EVENT_OBSERVER, data, reply, option); + if (result != ERR_NONE) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "failed, error code is: %{public}d", result); + } + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "end."); +} + +void PasteboardServiceProxy::ProcessObserver(uint32_t code, const sptr &observer) +{ + if (observer == nullptr) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "observer nullptr"); + return; + } + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "Failed to write parcelable"); + return; + } + if (!data.WriteRemoteObject(observer->AsObject())) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "Failed to write parcelable"); + return; + } + int32_t result = Remote()->SendRequest(code, data, reply, option); + if (result != ERR_NONE) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "failed, error code is: %{public}d", result); + } +} + +bool PasteboardServiceProxy::IsRemoteData() +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "start."); + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "Failed to write parcelable"); + return false; + } + + int32_t ret = Remote()->SendRequest(PasteboardServiceInterfaceCode::IS_REMOTE_DATA, data, reply, option); + if (ret != ERR_NONE) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "failed, error code is: %{public}d", ret); + return false; + } + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "end."); + return reply.ReadBool(); +} + +int32_t PasteboardServiceProxy::GetDataSource(std::string &bundleName) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "start."); + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "Failed to write parcelable"); + return ERR_INVALID_VALUE; + } + int32_t result = Remote()->SendRequest(PasteboardServiceInterfaceCode::GET_DATA_SOURCE, data, reply, option); + if (result != ERR_NONE) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "failed, error code is: %{public}d", result); + return ERR_INVALID_OPERATION; + } + bundleName = reply.ReadString(); + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "end."); + return reply.ReadInt32(); +} + +bool PasteboardServiceProxy::HasDataType(const std::string &mimeType) +{ + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "start."); + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "Failed to write parcelable"); + return ERR_INVALID_VALUE; + } + if (!data.WriteString(mimeType)) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "Failed to write string"); + return ERR_INVALID_VALUE; + } + int32_t result = Remote()->SendRequest(PasteboardServiceInterfaceCode::HAS_DATA_TYPE, data, reply, option); + if (result != ERR_NONE) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "failed, error code is: %{public}d", result); + return ERR_INVALID_OPERATION; + } + + PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "end."); + return reply.ReadBool(); +} +} // namespace MiscServices +} // namespace OHOS \ No newline at end of file diff --git a/pasteboard/services/zidl/src/pasteboard_service_stub.cpp b/pasteboard/services/zidl/src/pasteboard_service_stub.cpp new file mode 100644 index 00000000..75094b67 --- /dev/null +++ b/pasteboard/services/zidl/src/pasteboard_service_stub.cpp @@ -0,0 +1,293 @@ +/* + * Copyright (C) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "pasteboard_service_stub.h" + +#include "copy_uri_handler.h" +#include "errors.h" +#include "hiview_adapter.h" +#include "paste_data.h" +#include "paste_uri_handler.h" +#include "pasteboard_error.h" +#include "pasteboard_hilog.h" +#include "pasteboard_observer_proxy.h" +#include "pasteboard_serv_ipc_interface_code.h" + +using namespace OHOS::Security::PasteboardServ; +namespace OHOS { +namespace MiscServices { +PasteboardServiceStub::PasteboardServiceStub() +{ + memberFuncMap_[static_cast(PasteboardServiceInterfaceCode::GET_PASTE_DATA)] = + &PasteboardServiceStub::OnGetPasteData; + memberFuncMap_[static_cast(PasteboardServiceInterfaceCode::HAS_PASTE_DATA)] = + &PasteboardServiceStub::OnHasPasteData; + memberFuncMap_[static_cast(PasteboardServiceInterfaceCode::SET_PASTE_DATA)] = + &PasteboardServiceStub::OnSetPasteData; + memberFuncMap_[static_cast(PasteboardServiceInterfaceCode::CLEAR_ALL)] = &PasteboardServiceStub::OnClear; + memberFuncMap_[static_cast(PasteboardServiceInterfaceCode::ADD_CHANGED_OBSERVER)] = + &PasteboardServiceStub::OnAddPasteboardChangedObserver; + memberFuncMap_[static_cast(PasteboardServiceInterfaceCode::DELETE_CHANGED_OBSERVER)] = + &PasteboardServiceStub::OnRemovePasteboardChangedObserver; + memberFuncMap_[static_cast(PasteboardServiceInterfaceCode::DELETE_ALL_CHANGED_OBSERVER)] = + &PasteboardServiceStub::OnRemoveAllChangedObserver; + memberFuncMap_[static_cast(PasteboardServiceInterfaceCode::ADD_EVENT_OBSERVER)] = + &PasteboardServiceStub::OnAddPasteboardEventObserver; + memberFuncMap_[static_cast(PasteboardServiceInterfaceCode::DELETE_EVENT_OBSERVER)] = + &PasteboardServiceStub::OnRemovePasteboardEventObserver; + memberFuncMap_[static_cast(PasteboardServiceInterfaceCode::DELETE_ALL_EVENT_OBSERVER)] = + &PasteboardServiceStub::OnRemoveAllEventObserver; + memberFuncMap_[static_cast(PasteboardServiceInterfaceCode::IS_REMOTE_DATA)] = + &PasteboardServiceStub::OnIsRemoteData; + memberFuncMap_[static_cast(PasteboardServiceInterfaceCode::GET_DATA_SOURCE)] = + &PasteboardServiceStub::OnGetDataSource; + memberFuncMap_[static_cast(PasteboardServiceInterfaceCode::HAS_DATA_TYPE)] = + &PasteboardServiceStub::OnHasDataType; +} + +int32_t PasteboardServiceStub::OnRemoteRequest( + uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) +{ + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "start##code = %{public}u", code); + std::u16string myDescripter = PasteboardServiceStub::GetDescriptor(); + std::u16string remoteDescripter = data.ReadInterfaceToken(); + if (myDescripter != remoteDescripter) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "end##descriptor checked fail"); + return IPCObjectStub::OnRemoteRequest(code, data, reply, option); + } + pid_t p = IPCSkeleton::GetCallingPid(); + pid_t p1 = IPCSkeleton::GetCallingUid(); + PASTEBOARD_HILOGI( + PASTEBOARD_MODULE_SERVICE, "CallingPid = %{public}d, CallingUid = %{public}d, code = %{public}u", p, p1, code); + auto itFunc = memberFuncMap_.find(code); + if (itFunc != memberFuncMap_.end()) { + auto memberFunc = itFunc->second; + if (memberFunc != nullptr) { + return (this->*memberFunc)(data, reply); + } + } + int ret = IPCObjectStub::OnRemoteRequest(code, data, reply, option); + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "end##ret = %{public}d", ret); + return ret; +} +int32_t PasteboardServiceStub::OnClear(MessageParcel &data, MessageParcel &reply) +{ + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "start."); + Clear(); + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "end."); + return ERR_OK; +} + +int32_t PasteboardServiceStub::OnGetPasteData(MessageParcel &data, MessageParcel &reply) +{ + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, " start."); + PasteData pasteData{}; + auto result = GetPasteData(pasteData); + HiViewAdapter::ReportUseBehaviour(pasteData, HiViewAdapter::PASTE_STATE, result); + std::vector pasteDataTlv(0); + bool ret = pasteData.Encode(pasteDataTlv); + if (!ret) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "Failed to encode pastedata in TLV"); + return ERR_INVALID_VALUE; + } + if (!reply.WriteInt32(pasteDataTlv.size())) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "Failed to write raw size"); + return ERR_INVALID_VALUE; + } + if (!reply.WriteRawData(pasteDataTlv.data(), pasteDataTlv.size())) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "Failed to write raw data"); + return ERR_INVALID_VALUE; + } + PasteUriHandler pasteUriHandler; + if (!pasteData.WriteUriFd(reply, pasteUriHandler, false)) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "Failed to write uri fd"); + return ERR_INVALID_VALUE; + } + if (!reply.WriteInt32(result)) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "Failed to GetPasteData result"); + return ERR_INVALID_VALUE; + } + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, " end."); + return ERR_OK; +} +int32_t PasteboardServiceStub::OnHasPasteData(MessageParcel &data, MessageParcel &reply) +{ + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, " start."); + auto result = HasPasteData(); + reply.WriteBool(result); + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, " end."); + return ERR_OK; +} + +int32_t PasteboardServiceStub::OnSetPasteData(MessageParcel &data, MessageParcel &reply) +{ + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, " start."); + int32_t rawDataSize = data.ReadInt32(); + if (rawDataSize <= 0) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "Failed to read raw size"); + return ERR_INVALID_VALUE; + } + auto *rawData = (uint8_t *)data.ReadRawData(rawDataSize); + if (rawData == nullptr) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "Failed to get raw data"); + return ERR_INVALID_VALUE; + } + std::vector pasteDataTlv(rawData, rawData + rawDataSize); + auto pasteData = std::make_shared(); + bool ret = pasteData->Decode(pasteDataTlv); + if (!ret) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "Failed to decode pastedata in TLV"); + return ERR_INVALID_VALUE; + } + CopyUriHandler copyUriHandler; + if (!pasteData->ReadUriFd(data, copyUriHandler)) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "Failed to read uri fd"); + return ERR_INVALID_VALUE; + } + int32_t result = SavePasteData(pasteData); + HiViewAdapter::ReportUseBehaviour(*pasteData, HiViewAdapter::COPY_STATE, result); + if (!reply.WriteInt32(result)) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "Failed to write SetPasteData result"); + return ERR_INVALID_VALUE; + } + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, " end."); + return ERR_OK; +} +int32_t PasteboardServiceStub::OnAddPasteboardChangedObserver(MessageParcel &data, MessageParcel &reply) +{ + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "start."); + sptr callback; + if (!IsObserverValid(data, callback)) { + return ERR_INVALID_VALUE; + } + + AddPasteboardChangedObserver(callback); + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "end."); + return ERR_OK; +} +int32_t PasteboardServiceStub::OnRemovePasteboardChangedObserver(MessageParcel &data, MessageParcel &reply) +{ + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "start."); + sptr callback; + if (!IsObserverValid(data, callback)) { + return ERR_INVALID_VALUE; + } + RemovePasteboardChangedObserver(callback); + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "end."); + return ERR_OK; +} + +int32_t PasteboardServiceStub::OnRemoveAllChangedObserver(MessageParcel &data, MessageParcel &reply) +{ + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "start."); + RemoveAllChangedObserver(); + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "end."); + return ERR_OK; +} + +int32_t PasteboardServiceStub::OnAddPasteboardEventObserver(MessageParcel &data, MessageParcel &reply) +{ + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "start."); + sptr callback; + if (!IsObserverValid(data, callback)) { + return ERR_INVALID_VALUE; + } + + AddPasteboardEventObserver(callback); + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "end."); + return ERR_OK; +} + +int32_t PasteboardServiceStub::OnRemovePasteboardEventObserver(MessageParcel &data, MessageParcel &reply) +{ + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "start."); + sptr callback; + if (!IsObserverValid(data, callback)) { + return ERR_INVALID_VALUE; + } + RemovePasteboardEventObserver(callback); + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "end."); + return ERR_OK; +} + +int32_t PasteboardServiceStub::OnRemoveAllEventObserver(MessageParcel &data, MessageParcel &reply) +{ + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "start."); + RemoveAllEventObserver(); + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "end."); + return ERR_OK; +} + +inline bool PasteboardServiceStub::IsObserverValid(MessageParcel &data, sptr &callback) +{ + sptr obj = data.ReadRemoteObject(); + if (obj == nullptr) { + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "obj nullptr"); + return false; + } + callback = iface_cast(obj); + if (callback == nullptr) { + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "callback nullptr"); + return false; + } + return true; +} + +int32_t PasteboardServiceStub::OnIsRemoteData(MessageParcel &data, MessageParcel &reply) +{ + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "start."); + auto result = IsRemoteData(); + reply.WriteBool(result); + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "end."); + return ERR_OK; +} + +int32_t PasteboardServiceStub::OnGetDataSource(MessageParcel &data, MessageParcel &reply) +{ + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "start."); + std::string bundleName; + auto ret = GetDataSource(bundleName); + if (bundleName.empty() || bundleName.length() > MAX_BUNDLE_NAME_LENGTH) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "Failed to get bundleName"); + return ERR_INVALID_VALUE; + } + if (!reply.WriteString(bundleName)) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "Failed to writeName result"); + return ERR_INVALID_VALUE; + } + if (!reply.WriteInt32(ret)) { + PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "Failed to OnGetResourceApp result"); + return ERR_INVALID_VALUE; + } + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "end."); + return ERR_OK; +} + +int32_t PasteboardServiceStub::OnHasDataType(MessageParcel &data, MessageParcel &reply) +{ + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "start."); + std::string mimeType = data.ReadString(); + auto ret = HasDataType(mimeType); + reply.WriteBool(ret); + PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "end."); + return ERR_OK; +} + +PasteboardServiceStub::~PasteboardServiceStub() +{ + memberFuncMap_.clear(); +} +} // namespace MiscServices +} // namespace OHOS diff --git a/pasteboard/test/fuzztest/BUILD.gn b/pasteboard/test/fuzztest/BUILD.gn new file mode 100644 index 00000000..2a3d2196 --- /dev/null +++ b/pasteboard/test/fuzztest/BUILD.gn @@ -0,0 +1,24 @@ +# Copyright (c) 2022-2023 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//foundation/distributeddatamgr/pasteboard/pasteboard.gni") + +group("fuzztest") { + testonly = true + + deps = [ + "pasteboardclient_fuzzer:fuzztest", + "pasteboardservice_fuzzer:fuzztest", + "urihandler_fuzzer:fuzztest", + ] +} diff --git a/pasteboard/test/fuzztest/pasteboardclient_fuzzer/BUILD.gn b/pasteboard/test/fuzztest/pasteboardclient_fuzzer/BUILD.gn new file mode 100644 index 00000000..ae011082 --- /dev/null +++ b/pasteboard/test/fuzztest/pasteboardclient_fuzzer/BUILD.gn @@ -0,0 +1,66 @@ +# Copyright (c) 2022-2023 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//foundation/distributeddatamgr/pasteboard/pasteboard.gni") + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/ohos.gni") +import("//build/test.gni") + +##############################fuzztest########################################## +ohos_fuzztest("PasteboardClientFuzzTest") { + module_out_path = "pasteboard/pasteboard" + + fuzz_config_file = "//foundation/distributeddatamgr/pasteboard/test/fuzztest/pasteboardclient_fuzzer" + + configs = [ "//foundation/distributeddatamgr/pasteboard/framework/innerkits:pasteboard_client_config" ] + + include_dirs = [ + "//foundation/distributeddatamgr/pasteboard/framework/innerkits/include", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + sources = [ "pasteboardclient_fuzzer.cpp" ] + + deps = [ + "${pasteboard_innerkits_path}:pasteboard_client", + "//foundation/bundlemanager/bundle_framework/interfaces/inner_api/appexecfwk_core:appexecfwk_core", + ] + + external_deps = [ + "ability_base:want", + "ability_base:zuri", + "c_utils:utils", + "eventhandler:libeventhandler", + "hilog:libhilog", + "image_framework:image_native", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":PasteboardClientFuzzTest", + ] +} +############################################################################### diff --git a/pasteboard/test/fuzztest/pasteboardclient_fuzzer/corpus/init b/pasteboard/test/fuzztest/pasteboardclient_fuzzer/corpus/init new file mode 100644 index 00000000..d39bf870 --- /dev/null +++ b/pasteboard/test/fuzztest/pasteboardclient_fuzzer/corpus/init @@ -0,0 +1,14 @@ +# Copyright (c) 2022-2023 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +FUZZ \ No newline at end of file diff --git a/pasteboard/test/fuzztest/pasteboardclient_fuzzer/pasteboardclient_fuzzer.cpp b/pasteboard/test/fuzztest/pasteboardclient_fuzzer/pasteboardclient_fuzzer.cpp new file mode 100644 index 00000000..81d95236 --- /dev/null +++ b/pasteboard/test/fuzztest/pasteboardclient_fuzzer/pasteboardclient_fuzzer.cpp @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#include "pasteboard_client.h" +#include "pasteboard_observer.h" + +using namespace OHOS::MiscServices; + +namespace OHOS { +using namespace OHOS::Media; +using namespace OHOS::AAFwk; +constexpr size_t THRESHOLD = 10; +constexpr size_t OFFSET = 4; +constexpr size_t RANDNUM_ZERO = 0; +constexpr size_t LENGTH = 46; + +uint32_t ConvertToUint32(const uint8_t *ptr) +{ + if (ptr == nullptr) { + return 0; + } + uint32_t bigVar = (ptr[0] << 24) | (ptr[1] << 16) | (ptr[2] << 8) | (ptr[3]); + return bigVar; +} + +void FuzzPasteboardclient(const uint8_t *rawData, size_t size) +{ + std::shared_ptr pasteData = std::make_shared(); + std::shared_ptr pasteDataRecord = std::make_shared(); + uint32_t code = ConvertToUint32(rawData); + rawData = rawData + OFFSET; + size = size - OFFSET; + std::string str(reinterpret_cast(rawData), size); + + if (code == RANDNUM_ZERO) { + pasteData = PasteboardClient::GetInstance()->CreatePlainTextData(str); + pasteDataRecord = PasteboardClient::GetInstance()->CreatePlainTextRecord(str); + } else { + pasteData = PasteboardClient::GetInstance()->CreateUriData(Uri(str)); + pasteDataRecord = PasteboardClient::GetInstance()->CreateUriRecord(Uri(str)); + } + pasteData->AddRecord(pasteDataRecord); + std::vector buffer; + pasteData->Encode(buffer); + + PasteData pasteData2; + pasteData2.Decode(buffer); + pasteData2.HasMimeType(std::string(reinterpret_cast(rawData), size)); + pasteData2.RemoveRecordAt(code); + pasteData2.ReplaceRecordAt(code, pasteDataRecord); +} + +void FuzzPasteboard(const uint8_t *rawData, size_t size) +{ + std::shared_ptr pasteData = std::make_shared(); + std::shared_ptr pasteDataRecord = std::make_shared(); + uint32_t code = ConvertToUint32(rawData); + rawData = rawData + OFFSET; + size = size - OFFSET; + std::string str(reinterpret_cast(rawData), size); + + uint32_t color[100] = { code }; + InitializationOptions opts = { { 5, 7}, PixelFormat::ARGB_8888 }; + std::unique_ptr pixelMap = PixelMap::Create(color, sizeof(color)/sizeof(color[0]), opts); + std::shared_ptr pixelMapIn = move(pixelMap); + + std::vector kvData(LENGTH); + kvData = { *rawData }; + std::string mimetype = "image/jpg"; + + if (code == RANDNUM_ZERO) { + pasteData = PasteboardClient::GetInstance()->CreatePixelMapData(pixelMapIn); + pasteDataRecord = PasteboardClient::GetInstance()->CreatePixelMapRecord(pixelMapIn); + } else { + pasteData = PasteboardClient::GetInstance()->CreateKvData(mimetype, kvData); + pasteDataRecord = PasteboardClient::GetInstance()->CreateKvRecord(mimetype, kvData); + } + + pasteData->AddRecord(pasteDataRecord); + if (PasteboardClient::GetInstance()->HasPasteData()) { + PasteboardClient::GetInstance()->RemovePasteboardChangedObserver(nullptr); + } +} + +void FuzzPastedata(const uint8_t *rawData, size_t size) +{ + std::string str(reinterpret_cast(rawData), size); + PasteData pasteData2; + pasteData2.SetRemote(static_cast(*rawData)); + pasteData2.SetOrginAuthority(str); + pasteData2.SetBundleName(str); + pasteData2.SetTag(str); + pasteData2.SetTime(str); + pasteData2.IsValid(); + pasteData2.IsRemote(); + pasteData2.IsLocalPaste(); + pasteData2.GetLocalOnly(); + pasteData2.IsDraggedData(); + + pasteData2.GetOrginAuthority(); + pasteData2.GetTag(); + pasteData2.GetTime(); + PasteboardClient::GetInstance()->SetPasteData(pasteData2); + PasteboardClient::GetInstance()->HasDataType(std::string(reinterpret_cast(rawData), size)); + PasteboardClient::GetInstance()->IsRemoteData(); + + std::string bundlename = pasteData2.GetBundleName(); + PasteboardClient::GetInstance()->GetPasteData(pasteData2); + PasteboardClient::GetInstance()->GetDataSource(bundlename); + + pasteData2.SetInvalid(); + sptr remoteObject = nullptr; + PasteboardClient::GetInstance()->LoadSystemAbilitySuccess(remoteObject); + PasteboardClient::GetInstance()->LoadSystemAbilityFail(); + const wptr object; + PasteboardSaDeathRecipient death; + death.OnRemoteDied(object); + PasteboardClient::GetInstance()->OnRemoteSaDied(object); + PasteboardClient::GetInstance()->Clear(); +} + +void FuzzPasteboardclientCreateData(const uint8_t *rawData, size_t size) +{ + std::shared_ptr pasteData = std::make_shared(); + std::shared_ptr pasteDataRecord = std::make_shared(); + uint32_t code = ConvertToUint32(rawData); + rawData = rawData + OFFSET; + size = size - OFFSET; + std::string str(reinterpret_cast(rawData), size); + + std::shared_ptr want = std::make_shared(); + std::string key = "id"; + bool id = static_cast(*rawData); + Want wantIn = want->SetParam(key, id); + + if (code == RANDNUM_ZERO) { + pasteData = PasteboardClient::GetInstance()->CreateHtmlData(str); + pasteDataRecord = PasteboardClient::GetInstance()->CreateHtmlTextRecord(str); + } else { + pasteData = PasteboardClient::GetInstance()->CreateWantData(std::make_shared(wantIn)); + pasteDataRecord = PasteboardClient::GetInstance()->CreateWantRecord(std::make_shared(wantIn)); + } +} +} // namespace OHOS +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + if (size < OHOS::THRESHOLD) { + return 0; + } + /* Run your code on data */ + OHOS::FuzzPasteboardclient(data, size); + OHOS::FuzzPasteboard(data, size); + OHOS::FuzzPastedata(data, size); + OHOS::FuzzPasteboardclientCreateData(data, size); + return 0; +} diff --git a/pasteboard/test/fuzztest/pasteboardclient_fuzzer/pasteboardclient_fuzzer.h b/pasteboard/test/fuzztest/pasteboardclient_fuzzer/pasteboardclient_fuzzer.h new file mode 100644 index 00000000..a77dbce9 --- /dev/null +++ b/pasteboard/test/fuzztest/pasteboardclient_fuzzer/pasteboardclient_fuzzer.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef TEST_FUZZTEST_PASTEBOARDCLIENT_FUZZER_PASTEBOARDCLIENT_FUZZER_H +#define TEST_FUZZTEST_PASTEBOARDCLIENT_FUZZER_PASTEBOARDCLIENT_FUZZER_H + +#define FUZZ_PROJECT_NAME "pasteboardservice_fuzzer" + +#endif // TEST_FUZZTEST_PASTEBOARDCLIENT_FUZZER_PASTEBOARDCLIENT_FUZZER_H \ No newline at end of file diff --git a/pasteboard/test/fuzztest/pasteboardclient_fuzzer/project.xml b/pasteboard/test/fuzztest/pasteboardclient_fuzzer/project.xml new file mode 100644 index 00000000..23a13fe4 --- /dev/null +++ b/pasteboard/test/fuzztest/pasteboardclient_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 2000 + + 300 + + 4096 + + diff --git a/pasteboard/test/fuzztest/pasteboardservice_fuzzer/BUILD.gn b/pasteboard/test/fuzztest/pasteboardservice_fuzzer/BUILD.gn new file mode 100644 index 00000000..b58ce777 --- /dev/null +++ b/pasteboard/test/fuzztest/pasteboardservice_fuzzer/BUILD.gn @@ -0,0 +1,77 @@ +# Copyright (c) 2022-2023 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//foundation/distributeddatamgr/pasteboard/pasteboard.gni") + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/ohos.gni") +import("//build/test.gni") + +##############################fuzztest########################################## +ohos_fuzztest("PasteboardServiceFuzzTest") { + module_out_path = "pasteboard/pasteboard" + + fuzz_config_file = "//foundation/distributeddatamgr/pasteboard/test/fuzztest/pasteboardservice_fuzzer" + + configs = [ "//foundation/distributeddatamgr/pasteboard/services:pasteboard_service_config" ] + + include_dirs = [ + "${pasteboard_root_path}/framework/uri", + "${pasteboard_service_path}/zidl/include", + "${pasteboard_service_path}/core/include", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + sources = [ + "${pasteboard_root_path}/framework/uri/copy_uri_handler.cpp", + "pasteboardservice_fuzzer.cpp", + ] + + deps = [ + "${pasteboard_innerkits_path}:pasteboard_client", + "${pasteboard_root_path}/framework/uri:pasteboard_uri", + "//foundation/bundlemanager/bundle_framework/interfaces/inner_api/appexecfwk_core:appexecfwk_core", + "//foundation/distributeddatamgr/pasteboard/services:pasteboard_service", + ] + + external_deps = [ + "ability_base:want", + "ability_base:zuri", + "app_file_service:remote_file_share_native", + "c_utils:utils", + "eventhandler:libeventhandler", + "hilog:libhilog", + "image_framework:image_native", + "ipc:ipc_core", + "os_account:os_account_innerkits", + "safwk:system_ability_fwk", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":PasteboardServiceFuzzTest", + ] +} +############################################################################### diff --git a/pasteboard/test/fuzztest/pasteboardservice_fuzzer/corpus/init b/pasteboard/test/fuzztest/pasteboardservice_fuzzer/corpus/init new file mode 100644 index 00000000..d39bf870 --- /dev/null +++ b/pasteboard/test/fuzztest/pasteboardservice_fuzzer/corpus/init @@ -0,0 +1,14 @@ +# Copyright (c) 2022-2023 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +FUZZ \ No newline at end of file diff --git a/pasteboard/test/fuzztest/pasteboardservice_fuzzer/pasteboardservice_fuzzer.cpp b/pasteboard/test/fuzztest/pasteboardservice_fuzzer/pasteboardservice_fuzzer.cpp new file mode 100644 index 00000000..f16433b6 --- /dev/null +++ b/pasteboard/test/fuzztest/pasteboardservice_fuzzer/pasteboardservice_fuzzer.cpp @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "pasteboardservice_fuzzer.h" + +#include +#include +#include + +#include "copy_uri_handler.h" +#include "i_pasteboard_service.h" +#include "message_parcel.h" +#include "paste_data.h" +#include "pasteboard_service.h" +#include "pasteboard_serv_ipc_interface_code.h" + +using namespace OHOS::Security::PasteboardServ; +using namespace OHOS::MiscServices; + +namespace OHOS { +constexpr size_t THRESHOLD = 10; +constexpr int32_t OFFSET = 4; +const std::u16string PASTEBOARDSERVICE_INTERFACE_TOKEN = u"ohos.miscservices.pasteboard.IPasteboardService"; + +uint32_t ConvertToUint32(const uint8_t *ptr) +{ + if (ptr == nullptr) { + return 0; + } + uint32_t bigVar = (ptr[0] << 24) | (ptr[1] << 16) | (ptr[2] << 8) | (ptr[3]); + return bigVar; +} + +bool FuzzPasteboardService(const uint8_t *rawData, size_t size) +{ + uint32_t code = ConvertToUint32(rawData); + rawData = rawData + OFFSET; + size = size - OFFSET; + + MessageParcel data; + data.WriteInterfaceToken(PASTEBOARDSERVICE_INTERFACE_TOKEN); + data.WriteInt32(size); + data.WriteBuffer(rawData, size); + data.RewindRead(0); + MessageParcel reply; + MessageOption option; + + std::make_shared()->OnRemoteRequest(code, data, reply, option); + + return true; +} + +bool FuzzPasteboardServiceOnSetPasteData(const uint8_t *rawData, size_t size) +{ + rawData = rawData + OFFSET; + size = size - OFFSET; + + MessageParcel data; + data.WriteInterfaceToken(PASTEBOARDSERVICE_INTERFACE_TOKEN); + data.WriteInt32(size); + data.WriteBuffer(rawData, size); + data.RewindRead(0); + MessageParcel reply; + MessageOption option; + + std::make_shared()->OnRemoteRequest( + static_cast(PasteboardServiceInterfaceCode::SET_PASTE_DATA), data, reply, option); + + MessageParcel source; + std::make_shared()->OnRemoteRequest( + static_cast(PasteboardServiceInterfaceCode::HAS_PASTE_DATA), source, reply, option); + + std::make_shared()->OnRemoteRequest( + static_cast(PasteboardServiceInterfaceCode::GET_PASTE_DATA), source, reply, option); + + std::make_shared()->OnRemoteRequest( + static_cast(PasteboardServiceInterfaceCode::CLEAR_ALL), source, reply, option); + return true; +} + +bool FuzzPasteOnIsRemoteData(const uint8_t *rawData, size_t size) +{ + rawData = rawData + OFFSET; + size = size - OFFSET; + + MessageParcel data; + data.WriteInterfaceToken(PASTEBOARDSERVICE_INTERFACE_TOKEN); + data.WriteInt32(size); + data.WriteBuffer(rawData, size); + data.RewindRead(0); + MessageParcel reply; + MessageOption option; + + std::make_shared()->OnRemoteRequest( + static_cast(PasteboardServiceInterfaceCode::IS_REMOTE_DATA), data, reply, option); + + std::make_shared()->OnRemoteRequest( + static_cast(PasteboardServiceInterfaceCode::GET_DATA_SOURCE), data, reply, option); + + std::make_shared()->OnRemoteRequest( + static_cast(PasteboardServiceInterfaceCode::HAS_DATA_TYPE), data, reply, option); + + return true; +} + +bool FuzzPasteOnAddChangedObserver(const uint8_t *rawData, size_t size) +{ + rawData = rawData + OFFSET; + size = size - OFFSET; + + MessageParcel data; + data.WriteInterfaceToken(PASTEBOARDSERVICE_INTERFACE_TOKEN); + data.WriteInt32(size); + data.WriteBuffer(rawData, size); + data.RewindRead(0); + MessageParcel reply; + MessageOption option; + + std::make_shared()->OnRemoteRequest( + static_cast(PasteboardServiceInterfaceCode::ADD_CHANGED_OBSERVER), data, reply, option); + + std::make_shared()->OnRemoteRequest( + static_cast(PasteboardServiceInterfaceCode::DELETE_CHANGED_OBSERVER), data, reply, option); + + std::make_shared()->OnRemoteRequest( + static_cast(PasteboardServiceInterfaceCode::DELETE_ALL_CHANGED_OBSERVER), data, reply, option); + + return true; +} + +bool FuzzPasteOnAddEventObserver(const uint8_t *rawData, size_t size) +{ + rawData = rawData + OFFSET; + size = size - OFFSET; + + MessageParcel data; + data.WriteInterfaceToken(PASTEBOARDSERVICE_INTERFACE_TOKEN); + data.WriteInt32(size); + data.WriteBuffer(rawData, size); + data.RewindRead(0); + MessageParcel reply; + MessageOption option; + + std::make_shared()->OnRemoteRequest( + static_cast(PasteboardServiceInterfaceCode::ADD_EVENT_OBSERVER), data, reply, option); + + std::make_shared()->OnRemoteRequest( + static_cast(PasteboardServiceInterfaceCode::DELETE_EVENT_OBSERVER), data, reply, option); + + std::make_shared()->OnRemoteRequest( + static_cast(PasteboardServiceInterfaceCode::DELETE_ALL_EVENT_OBSERVER), data, reply, option); + + return true; +} +} // namespace OHOS +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + if (size < OHOS::THRESHOLD) { + return 0; + } + /* Run your code on data */ + OHOS::FuzzPasteboardService(data, size); + OHOS::FuzzPasteboardServiceOnSetPasteData(data, size); + OHOS::FuzzPasteOnIsRemoteData(data, size); + OHOS::FuzzPasteOnAddChangedObserver(data, size); + OHOS::FuzzPasteOnAddEventObserver(data, size); + return 0; +} diff --git a/pasteboard/test/fuzztest/pasteboardservice_fuzzer/pasteboardservice_fuzzer.h b/pasteboard/test/fuzztest/pasteboardservice_fuzzer/pasteboardservice_fuzzer.h new file mode 100644 index 00000000..62bbc86b --- /dev/null +++ b/pasteboard/test/fuzztest/pasteboardservice_fuzzer/pasteboardservice_fuzzer.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef TEST_FUZZTEST_PASTEBOARDSERVICE_FUZZER_PASTEBOARDSERVICE_FUZZER_H +#define TEST_FUZZTEST_PASTEBOARDSERVICE_FUZZER_PASTEBOARDSERVICE_FUZZER_H + +#define FUZZ_PROJECT_NAME "pasteboardservice_fuzzer" + +#endif // TEST_FUZZTEST_PASTEBOARDSERVICE_FUZZER_PASTEBOARDSERVICE_FUZZER_H \ No newline at end of file diff --git a/pasteboard/test/fuzztest/pasteboardservice_fuzzer/project.xml b/pasteboard/test/fuzztest/pasteboardservice_fuzzer/project.xml new file mode 100644 index 00000000..4fbbf8fa --- /dev/null +++ b/pasteboard/test/fuzztest/pasteboardservice_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/pasteboard/test/fuzztest/urihandler_fuzzer/BUILD.gn b/pasteboard/test/fuzztest/urihandler_fuzzer/BUILD.gn new file mode 100644 index 00000000..8f367067 --- /dev/null +++ b/pasteboard/test/fuzztest/urihandler_fuzzer/BUILD.gn @@ -0,0 +1,63 @@ +# Copyright (c) 2022-2023 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//foundation/distributeddatamgr/pasteboard/pasteboard.gni") + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/ohos.gni") +import("//build/test.gni") + +##############################fuzztest########################################## +ohos_fuzztest("UriHandlerFuzzTest") { + module_out_path = "pasteboard/pasteboard" + + fuzz_config_file = "${pasteboard_root_path}/test/fuzztest/urihandler_fuzzer" + + include_dirs = [ "${pasteboard_root_path}/framework/uri" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + sources = [ + "${pasteboard_root_path}/framework/uri/copy_uri_handler.cpp", + "urihandler_fuzzer.cpp", + ] + + deps = [ + "${pasteboard_innerkits_path}:pasteboard_client", + "${pasteboard_root_path}/framework/uri:pasteboard_uri", + ] + + external_deps = [ + "ability_base:zuri", + "app_file_service:remote_file_share_native", + "c_utils:utils", + "hilog:libhilog", + "image_framework:image_native", + "os_account:os_account_innerkits", + "safwk:system_ability_fwk", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ ":UriHandlerFuzzTest" ] +} +############################################################################### diff --git a/pasteboard/test/fuzztest/urihandler_fuzzer/corpus/init b/pasteboard/test/fuzztest/urihandler_fuzzer/corpus/init new file mode 100644 index 00000000..d39bf870 --- /dev/null +++ b/pasteboard/test/fuzztest/urihandler_fuzzer/corpus/init @@ -0,0 +1,14 @@ +# Copyright (c) 2022-2023 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +FUZZ \ No newline at end of file diff --git a/pasteboard/test/fuzztest/urihandler_fuzzer/project.xml b/pasteboard/test/fuzztest/urihandler_fuzzer/project.xml new file mode 100644 index 00000000..4fbbf8fa --- /dev/null +++ b/pasteboard/test/fuzztest/urihandler_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/pasteboard/test/fuzztest/urihandler_fuzzer/urihandler_fuzzer.cpp b/pasteboard/test/fuzztest/urihandler_fuzzer/urihandler_fuzzer.cpp new file mode 100644 index 00000000..73825937 --- /dev/null +++ b/pasteboard/test/fuzztest/urihandler_fuzzer/urihandler_fuzzer.cpp @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "urihandler_fuzzer.h" + +#include "copy_uri_handler.h" + +using namespace OHOS::MiscServices; + +namespace OHOS { +constexpr size_t THRESHOLD = 10; +constexpr size_t OFFSET = 4; +uint32_t ConvertToUint32(const uint8_t *ptr) +{ + if (ptr == nullptr) { + return 0; + } + uint32_t bigVar = (ptr[0] << 24) | (ptr[1] << 16) | (ptr[2] << 8) | (ptr[3]); + return bigVar; +} + +bool FuzzUriToFd(const uint8_t *rawData, size_t size) +{ + uint32_t value = ConvertToUint32(rawData); + rawData = rawData + OFFSET; + size = size - OFFSET; + std::string uri(reinterpret_cast(rawData), size); + bool isClient = value % 2; + CopyUriHandler uriHandler; + uriHandler.ToFd(uri, isClient); + return true; +} +} // namespace OHOS + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + if (size < OHOS::THRESHOLD) { + return 0; + } + /* Run your code on data */ + OHOS::FuzzUriToFd(data, size); + return 0; +} diff --git a/pasteboard/test/fuzztest/urihandler_fuzzer/urihandler_fuzzer.h b/pasteboard/test/fuzztest/urihandler_fuzzer/urihandler_fuzzer.h new file mode 100644 index 00000000..4931696e --- /dev/null +++ b/pasteboard/test/fuzztest/urihandler_fuzzer/urihandler_fuzzer.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef TEST_FUZZTEST_URIHANDLER_FUZZER_URIHANDLER_FUZZER_H +#define TEST_FUZZTEST_URIHANDLER_FUZZER_URIHANDLER_FUZZER_H + +#define FUZZ_PROJECT_NAME "urihandler_fuzzer" + +#endif // TEST_FUZZTEST_URIHANDLER_FUZZER_URIHANDLER_FUZZER_H \ No newline at end of file diff --git a/pasteboard/utils/native/include/pasteboard_error.h b/pasteboard/utils/native/include/pasteboard_error.h new file mode 100644 index 00000000..512cb435 --- /dev/null +++ b/pasteboard/utils/native/include/pasteboard_error.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef PASTEBOARD_ERROR_H +#define PASTEBOARD_ERROR_H + +#include "errors.h" +#include "pasteboard_hilog.h" + +namespace OHOS { +namespace MiscServices { +enum PasteboardModule { + PASTEBOARD_MODULE_SERVICE_ID = 0x06, +}; + +// Pasteboard error offset, used only in this file. +constexpr ErrCode PASTEBOARD_ERR_OFFSET = ErrCodeOffset(SUBSYS_SMALLSERVICES, PASTEBOARD_MODULE_SERVICE_ID); + +enum class PasteboardError : int32_t { + E_OK = PASTEBOARD_ERR_OFFSET, + E_INVALID_VALUE, + E_INVALID_OPTION, + E_WRITE_PARCEL_ERROR, + E_READ_PARCEL_ERROR, + E_SA_DIED, + E_ERROR, + E_OUT_OF_RANGE, + E_NO_PERMISSION, + E_INVALID_PARAMETERS, + E_TIMEOUT, + E_CANCELED, + E_EXCEEDS_LIMIT, + E_IS_BEGING_PROCESSED, + E_COPY_FORBIDDEN, + E_UNKNOWN, + E_BUTT, + E_REMOTE, +}; + +const std::map PasteboardErrorMap = { + {PasteboardError::E_OK, "E_OK"}, + {PasteboardError::E_INVALID_VALUE, "E_INVALID_VALUE"}, + {PasteboardError::E_INVALID_OPTION, "E_INVALID_OPTION"}, + {PasteboardError::E_WRITE_PARCEL_ERROR, "E_WRITE_PARCEL_ERROR"}, + {PasteboardError::E_READ_PARCEL_ERROR, "E_READ_PARCEL_ERROR"}, + {PasteboardError::E_SA_DIED, "E_SA_DIED"}, + {PasteboardError::E_ERROR, "E_ERROR"}, + {PasteboardError::E_OUT_OF_RANGE, "E_OUT_OF_RANGE"}, + {PasteboardError::E_NO_PERMISSION, "E_NO_PERMISSION"}, + {PasteboardError::E_INVALID_PARAMETERS, "E_INVALID_PARAMETERS"}, + {PasteboardError::E_TIMEOUT, "E_TIMEOUT"}, + {PasteboardError::E_CANCELED, "E_CANCELED"}, + {PasteboardError::E_EXCEEDS_LIMIT, "E_EXCEEDS_LIMIT"}, + {PasteboardError::E_IS_BEGING_PROCESSED, "E_IS_BEGING_PROCESSED"}, + {PasteboardError::E_COPY_FORBIDDEN, "E_COPY_FORBIDDEN"}, + {PasteboardError::E_UNKNOWN, "E_UNKNOWN"}, + {PasteboardError::E_BUTT, "E_BUTT"}, + {PasteboardError::E_REMOTE, "E_REMOTE"}, +}; + +} // namespace MiscServices +} // namespace OHOS +#endif // PASTEBOARD_ERROR_H \ No newline at end of file diff --git a/pasteboard/utils/native/include/pasteboard_hilog.h b/pasteboard/utils/native/include/pasteboard_hilog.h new file mode 100644 index 00000000..c51e173f --- /dev/null +++ b/pasteboard/utils/native/include/pasteboard_hilog.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef PASTEBOARD_HILOG_H +#define PASTEBOARD_HILOG_H + +#include "hilog/log.h" + +namespace OHOS { +namespace MiscServices { +// param of log interface, such as PASTEBOARD_HILOGF. +enum PasteboardSubModule { + PASTEBOARD_MODULE_INNERKIT = 0, + PASTEBOARD_MODULE_CLIENT, + PASTEBOARD_MODULE_SERVICE, + PASTEBOARD_MODULE_JAVAKIT, // java kit, defined to avoid repeated use of domain. + PASTEBOARD_MODULE_JNI, + PASTEBOARD_MODULE_COMMON, + PASTEBOARD_MODULE_JS_NAPI, + PASTEBOARD_MODULE_BUTT, +}; + +// 0xD001C00: subsystem:PASTEBOARD module:PasteboardManager, 8 bits reserved. +static constexpr unsigned int BASE_PASTEBOARD_DOMAIN_ID = 0xD001C00; + +enum PasteboardDomainId { + PASTEBOARD_INNERKIT_DOMAIN = BASE_PASTEBOARD_DOMAIN_ID + PASTEBOARD_MODULE_INNERKIT, + PASTEBOARD_CLIENT_DOMAIN, + PASTEBOARD_SERVICE_DOMAIN, + PASTEBOARD_JAVAKIT_DOMAIN, + PASTEBOARD_JNI_DOMAIN, + PASTEBOARD_COMMON_DOMAIN, + PASTEBOARD_JS_NAPI, + PASTEBOARD_BUTT, +}; + +static constexpr OHOS::HiviewDFX::HiLogLabel PASTEBOARD_MODULE_LABEL[PASTEBOARD_MODULE_BUTT] = { + { LOG_CORE, PASTEBOARD_INNERKIT_DOMAIN, "PasteboardInnerKit" }, + { LOG_CORE, PASTEBOARD_CLIENT_DOMAIN, "PasteboardClient" }, + { LOG_CORE, PASTEBOARD_SERVICE_DOMAIN, "PasteboardService" }, + { LOG_CORE, PASTEBOARD_JAVAKIT_DOMAIN, "PasteboardJavaKit" }, + { LOG_CORE, PASTEBOARD_JNI_DOMAIN, "PasteboardJni" }, + { LOG_CORE, PASTEBOARD_COMMON_DOMAIN, "PasteboardCommon" }, + { LOG_CORE, PASTEBOARD_JS_NAPI, "PasteboardJSNAPI" }, +}; + +#define FILENAME__ (__builtin_strrchr(__FILE__, '/') ? __builtin_strrchr(__FILE__, '/') + 1 : __FILE__) +#define FORMATED__(fmt, ...) "[%{public}s] %{public}s# " fmt, FILENAME__, __FUNCTION__, ##__VA_ARGS__ + +// In order to improve performance, do not check the module range. +// Besides, make sure module is less than PASTEBOARD_MODULE_BUTT. +#define PASTEBOARD_HILOGF(module, ...) \ + (void)OHOS::HiviewDFX::HiLog::Fatal(PASTEBOARD_MODULE_LABEL[module], FORMATED__(__VA_ARGS__)) +#define PASTEBOARD_HILOGE(module, ...) \ + (void)OHOS::HiviewDFX::HiLog::Error(PASTEBOARD_MODULE_LABEL[module], FORMATED__(__VA_ARGS__)) +#define PASTEBOARD_HILOGW(module, ...) \ + (void)OHOS::HiviewDFX::HiLog::Warn(PASTEBOARD_MODULE_LABEL[module], FORMATED__(__VA_ARGS__)) +#define PASTEBOARD_HILOGI(module, ...) \ + (void)OHOS::HiviewDFX::HiLog::Info(PASTEBOARD_MODULE_LABEL[module], FORMATED__(__VA_ARGS__)) +#define PASTEBOARD_HILOGD(module, ...) \ + (void)OHOS::HiviewDFX::HiLog::Debug(PASTEBOARD_MODULE_LABEL[module], FORMATED__(__VA_ARGS__)) +} // namespace MiscServices +} // namespace OHOS + +#endif // PASTEBOARD_HILOG_H diff --git a/pasteboard/utils/native/include/pasteboard_sp_singleton.h b/pasteboard/utils/native/include/pasteboard_sp_singleton.h new file mode 100644 index 00000000..86bc35c8 --- /dev/null +++ b/pasteboard/utils/native/include/pasteboard_sp_singleton.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PASTEBOARD_SP_SINGLETON_H +#define PASTEBOARD_SP_SINGLETON_H + +#include +#include +#include + +#include "nocopyable.h" + +namespace OHOS { +namespace MiscServices { +#define DECLARE_DELAYED_SP_SINGLETON(MyClass) \ +public: \ + ~MyClass(); \ + \ +private: \ + friend DelayedSpSingleton; \ + MyClass(); + +template +class DelayedSpSingleton : public NoCopyable { +public: + static sptr GetInstance(); + static void DestroyInstance(); + +private: + static sptr instance_; + static std::mutex mutex_; +}; + +template +sptr DelayedSpSingleton::instance_ = nullptr; + +template +std::mutex DelayedSpSingleton::mutex_; + +template +sptr DelayedSpSingleton::GetInstance() +{ + if (!instance_) { + std::lock_guard lock(mutex_); + if (instance_ == nullptr) { + instance_ = new T(); + } + } + + return instance_; +} + +template +void DelayedSpSingleton::DestroyInstance() +{ + std::lock_guard lock(mutex_); + if (instance_) { + instance_.clear(); + instance_ = nullptr; + } +} +} // namespace MiscServices +} // namespace OHOS +#endif -- Gitee