diff --git a/CMakeLists.txt b/CMakeLists.txt index 6f72376e24..89fce0a935 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -148,6 +148,10 @@ if(PLUGIN_STORAGE_MANAGER) add_subdirectory(StorageManager) endif() +if(PLUGIN_NATIVEJS) + add_subdirectory(NativeJS) +endif() + if(PLUGIN_DEVICE_PROVISIONING) add_subdirectory(DeviceProvisioning) endif() diff --git a/NativeJS/CMakeLists.txt b/NativeJS/CMakeLists.txt new file mode 100644 index 0000000000..e3ad3b5b87 --- /dev/null +++ b/NativeJS/CMakeLists.txt @@ -0,0 +1,24 @@ +set(PLUGIN_NAME NativeJS) +set(MODULE_NAME ${NAMESPACE}${PLUGIN_NAME}) + +find_package(${NAMESPACE}Plugins REQUIRED) +find_package(${NAMESPACE}Definitions REQUIRED) + +add_library(${MODULE_NAME} SHARED + NativeJSPlugin.cpp + NativeJSImplementation.cpp + Module.cpp +) + +set_target_properties(${MODULE_NAME} PROPERTIES + CXX_STANDARD 17 + CXX_STANDARD_REQUIRED YES) + +target_include_directories(${MODULE_NAME} PRIVATE ../helpers $ENV{PKG_CONFIG_SYSROOT_DIR}/usr/include/jsruntime ${CMAKE_CURRENT_SOURCE_DIR} ) + +target_link_libraries(${MODULE_NAME} PRIVATE ${NAMESPACE}Plugins::${NAMESPACE}Plugins ${NAMESPACE}Definitions::${NAMESPACE}Definitions -L${CMAKE_CURRENT_SOURCE_DIR}/../../build/NativeJS -L$ENV{PKG_CONFIG_SYSROOT_DIR}/usr/lib/javascriptcore -lJSRuntimeJSC -lJavaScriptCore) + +install(TARGETS ${MODULE_NAME} + DESTINATION lib/${STORAGE_DIRECTORY}/plugins) + +write_config(${PLUGIN_NAME}) diff --git a/NativeJS/Module.cpp b/NativeJS/Module.cpp new file mode 100644 index 0000000000..ce759b615f --- /dev/null +++ b/NativeJS/Module.cpp @@ -0,0 +1,22 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2019 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT 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 "Module.h" + +MODULE_NAME_DECLARATION(BUILD_REFERENCE) diff --git a/NativeJS/Module.h b/NativeJS/Module.h new file mode 100644 index 0000000000..94550425b0 --- /dev/null +++ b/NativeJS/Module.h @@ -0,0 +1,29 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2019 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ + +#pragma once +#ifndef MODULE_NAME +#define MODULE_NAME NativeJS +#endif + +#include +#include + +#undef EXTERNAL +#define EXTERNAL diff --git a/NativeJS/NativeJS.conf.in b/NativeJS/NativeJS.conf.in new file mode 100644 index 0000000000..50b1515f2f --- /dev/null +++ b/NativeJS/NativeJS.conf.in @@ -0,0 +1,8 @@ +autostart = "false" +precondition = ["Graphics"] +callsign = "org.rdk.jsruntime" +configuration = JSON() +root = JSON() +root.add("mode", "Local") +configuration.add("root", root) +configuration.add("clientidentifier", "test") diff --git a/NativeJS/NativeJS.config b/NativeJS/NativeJS.config new file mode 100644 index 0000000000..49adbb2323 --- /dev/null +++ b/NativeJS/NativeJS.config @@ -0,0 +1,17 @@ +set (autostart false) +set (preconditions Graphics) +set (callsign "org.rdk.JSRuntime") + +map() + kv(outofprocess true) +end() +ans(rootobject) + +map() + if(PLUGIN_NATIVEJS_CLIENTIDENTIFIER) + kv(clientidentifier ${PLUGIN_NATIVEJS_CLIENTIDENTIFIER}) + endif() +end() +ans(configuration) + +map_append(${configuration} root ${rootobject}) diff --git a/NativeJS/NativeJSImplementation.cpp b/NativeJS/NativeJSImplementation.cpp new file mode 100644 index 0000000000..d52ff21abb --- /dev/null +++ b/NativeJS/NativeJSImplementation.cpp @@ -0,0 +1,159 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2020 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT 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 "NativeJSImplementation.h" + +using namespace std; + +namespace WPEFramework +{ + namespace Plugin + { + + std::string gPendingIdRequest(""); + std::string gPendingIdOptionsRequest(""); + std::string gPendingUrl(""); + SERVICE_REGISTRATION(NativeJSImplementation, 1, 0); + + NativeJSImplementation::NativeJSImplementation() + : mRunning(true) + { + TRACE(Trace::Information, (_T("Constructing NativeJSImplementation Service: %p"), this)); + } + + NativeJSImplementation::~NativeJSImplementation() + { + TRACE(Trace::Information, (_T("Destructing NativeJSImplementation Service: %p"), this)); + mNativeJSRenderer = nullptr; + } + + Core::hresult NativeJSImplementation::Initialize(string waylandDisplay) + { + std::cout << "initialize called on nativejs implementation " << std::endl; + mRenderThread = std::thread([=](std::string waylandDisplay) { + mNativeJSRenderer = std::make_shared(waylandDisplay); + //if (!gPendingUrlRequest.empty()) + //{ + // ModuleSettings moduleSettings; + // moduleSettings.fromString(gPendingUrlOptionsRequest); + // mNativeJSRenderer->launchApplication(gPendingUrlRequest, moduleSettings); + // gPendingUrlRequest = ""; + // gPendingUrlOptionsRequest = ""; + //} + + mNativeJSRenderer->run(); + + printf("After launch application execution ... \n"); fflush(stdout); + mNativeJSRenderer.reset(); + + }, waylandDisplay); + return (Core::ERROR_NONE); + } + + Core::hresult NativeJSImplementation::Deinitialize() + { + LOGINFO("deinitializing NativeJS process"); + if (mNativeJSRenderer) + { + mNativeJSRenderer->terminate(); + if (mRenderThread.joinable()) + { + mRenderThread.join(); + } + } + return (Core::ERROR_NONE); + } + + Core::hresult NativeJSImplementation::CreateApplication(const std::string options, uint32_t& id) + { + LOGINFO("createApplication invoked"); + if(mNativeJSRenderer) + { + std::string optionsVal(options); + ModuleSettings moduleSettings; + moduleSettings.fromString(optionsVal); + id = mNativeJSRenderer->createApplication(moduleSettings); + } + else + { + gPendingIdOptionsRequest = options; + } + return (Core::ERROR_NONE); + } + + Core::hresult NativeJSImplementation::RunApplication(uint32_t id, const std::string url) + { + LOGINFO("runApplication invoked"); + if(mNativeJSRenderer) + { + std::string Url(url); + mNativeJSRenderer->runApplication(id, Url); + } + else + { + gPendingUrl = url; + LOGINFO("runApplication Couldn't execute"); + } + return (Core::ERROR_NONE); + } + + Core::hresult NativeJSImplementation::RunJavaScript(uint32_t id, const std::string code) + { + LOGINFO("runJavaScript invoked"); + if(mNativeJSRenderer) + { + std::string Code(code); + mNativeJSRenderer->runJavaScript(id, Code); + } + else + { + LOGINFO("runJavaScript couldn't execute"); + } + return (Core::ERROR_NONE); + } + + Core::hresult NativeJSImplementation::GetApplications() + { + LOGINFO("getApplication invoked"); + if(mNativeJSRenderer) + { + mNativeJSRenderer->getApplications(); + } + else + { + LOGINFO("getApplication couldn't execute"); + } + return (Core::ERROR_NONE); + } + + Core::hresult NativeJSImplementation::TerminateApplication(uint32_t id) + { + LOGINFO("terminateApplication invoked"); + if(mNativeJSRenderer) + { + mNativeJSRenderer->terminateApplication(id); + } + else + { + LOGINFO("Application couldn't be terminated"); + } + return (Core::ERROR_NONE); + } +} // namespace Plugin +} // namespace WPEFramework diff --git a/NativeJS/NativeJSImplementation.h b/NativeJS/NativeJSImplementation.h new file mode 100644 index 0000000000..cc3b9d7de9 --- /dev/null +++ b/NativeJS/NativeJSImplementation.h @@ -0,0 +1,61 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2020 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ + +#pragma once + +#include "Module.h" +#include "UtilsLogging.h" +#include +#include + +#include +#include "NativeJSRenderer.h" +#include +#include +using namespace JsRuntime; + +namespace WPEFramework +{ + namespace Plugin + { + + class NativeJSImplementation : public Exchange::INativeJS + { + public: + NativeJSImplementation(); + virtual ~NativeJSImplementation(); + virtual Core::hresult Initialize(const string waylandDisplay) override; + virtual Core::hresult Deinitialize() override; + virtual Core::hresult CreateApplication(const std::string options, uint32_t& id) override; + virtual Core::hresult GetApplications() override; + virtual Core::hresult RunApplication(uint32_t id, const std::string url) override; + virtual Core::hresult RunJavaScript(uint32_t id, const std::string code) override; + virtual Core::hresult TerminateApplication(uint32_t id) override; + + BEGIN_INTERFACE_MAP(NativeJSImplementation) + INTERFACE_ENTRY(Exchange::INativeJS) + END_INTERFACE_MAP + + private: + std::thread mRenderThread; + bool mRunning; + std::shared_ptr mNativeJSRenderer; + }; + } // namespace Plugin +} // namespace WPEFramework diff --git a/NativeJS/NativeJSPlugin.cpp b/NativeJS/NativeJSPlugin.cpp new file mode 100644 index 0000000000..03fcb3b011 --- /dev/null +++ b/NativeJS/NativeJSPlugin.cpp @@ -0,0 +1,103 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2020 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT 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 "NativeJSPlugin.h" + +const string WPEFramework::Plugin::NativeJS::SERVICE_NAME = "org.rdk.NativeJS"; + +using namespace std; + +namespace WPEFramework { + namespace Plugin { + + SERVICE_REGISTRATION(NativeJS, 1, 0); + + NativeJS* NativeJS::_instance = nullptr; + + NativeJS::NativeJS() + : PluginHost::IPlugin(), PluginHost::JSONRPC(), mService(nullptr), mNativeJS(nullptr) + { + NativeJS::_instance = this; + } + + NativeJS::~NativeJS() + { + } + + const string NativeJS::Initialize(PluginHost::IShell* service ) + { + string message; + + ASSERT(mService == nullptr); + ASSERT(mNativeJS == nullptr); + + mConnectionId = 0; + mService = service; + + mNativeJS = mService->Root(mConnectionId, 5000, _T("NativeJSImplementation")); + + if (mNativeJS == nullptr) + { + message = _T("NativeJS implementation could not be instantiated."); + mService = nullptr; + return message; + } + std::string waylandDisplay(""); + mConfig.FromString(service->ConfigLine()); + if (mConfig.Display.IsSet() == true) + { + waylandDisplay = mConfig.Display.Value(); + } + else + { + const char* display = getenv("WAYLAND_DISPLAY"); + if (NULL != display) + { + waylandDisplay = display; + } + } + mNativeJS->Initialize(waylandDisplay); + Exchange::JNativeJS::Register(*this, mNativeJS); + return ""; + } + + void NativeJS::Deinitialize(PluginHost::IShell* /* service */) + { + LOGINFO("Deinitializing NativeJS instance"); + if (mNativeJS != nullptr) { + + Exchange::JNativeJS::Unregister(*this); + mNativeJS->Deinitialize(); + + mNativeJS->Release(); + mNativeJS = nullptr; + mService = nullptr; + NativeJS::_instance = nullptr; + LOGINFO("NativeJS deinitialized successfully"); + + } + } + + string NativeJS::Information() const + { + return(string("{\"service\": \"") + SERVICE_NAME + string("\"}")); + } + + } // namespace Plugin +} // namespace WPEFramework diff --git a/NativeJS/NativeJSPlugin.h b/NativeJS/NativeJSPlugin.h new file mode 100644 index 0000000000..64ab7014d7 --- /dev/null +++ b/NativeJS/NativeJSPlugin.h @@ -0,0 +1,88 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2020 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ + +#pragma once + +#include "Module.h" +#include "UtilsLogging.h" +#include "UtilsJsonRpc.h" +#include +#include +#include + +namespace WPEFramework { + + namespace Plugin { + + class NativeJS : public PluginHost::IPlugin, public PluginHost::JSONRPC { + public: + class Config : public Core::JSON::Container + { + private: + Config(const Config&) = delete; + Config& operator=(const Config&) = delete; + + public: + Config() + : Core::JSON::Container() + , Display(_T("")) + { + Add(_T("embedthunderjs"), &EmbedThunderJS); + Add(_T("clientidentifier"), &Display); + } + ~Config() + { + } + + public: + Core::JSON::Boolean EmbedThunderJS; + Core::JSON::String Display; + }; + + BEGIN_INTERFACE_MAP(NativeJSPlugin) + INTERFACE_AGGREGATE(Exchange::INativeJS, mNativeJS) + INTERFACE_ENTRY(PluginHost::IPlugin) + INTERFACE_ENTRY(PluginHost::IDispatcher) + END_INTERFACE_MAP + + public: + NativeJS(); + virtual ~NativeJS(); + virtual const string Initialize(PluginHost::IShell* service) override; + virtual void Deinitialize(PluginHost::IShell* service) override; + virtual string Information() const override; + + public/*members*/: + static NativeJS* _instance; + + public /*constants*/: + static const string SERVICE_NAME; + + private/*registered methods (wrappers)*/: + + NativeJS(const NativeJS&) = delete; + NativeJS& operator=(const NativeJS&) = delete; + + PluginHost::IShell* mService; + uint32_t mConnectionId; + Exchange::INativeJS* mNativeJS; + Config mConfig; + }; + } // namespace Plugin +} // namespace WPEFramework diff --git a/NativeJS/README.md b/NativeJS/README.md new file mode 100644 index 0000000000..b3d0265f42 --- /dev/null +++ b/NativeJS/README.md @@ -0,0 +1,31 @@ +----------------- +# NativeJS + +## Versions +`org.rdk.jsruntime.1` + +## Properties: +``` +## Methods: +``` +TO laucnch the application +curl --header "Content-Type: application/json"  -H "$token" --request POST --data '{"jsonrpc":"2.0","id":"3","method": "org.rdk.jsruntime.1.launchApplication", "params":{"url":"http://127.0.0.1:50050/demo/helloworld.js"}}' http://127.0.0.1:9998/jsonrpc + +Destory the application +curl --header "Content-Type: application/json" -H "$token" --request POST --data '{"jsonrpc":"2.0","id":"3","method": "org.rdk.jsruntime.1.destroyApplication", "params":{"url":"http://127.0.0.1:50050/demo/player.js"}' http://127.0.0.1:9998/jsonrpc + +To play video content on display, pass player in options parameter +curl --header "Content-Type: application/json"  -H "$token" --request POST --data '{"jsonrpc":"2.0","id":"3","method": "org.rdk.jsruntime.1.launchApplication", "params":{"url":"http://127.0.0.1:50050/demo/helloworld.js", "options": "player"}}' http://127.0.0.1:9998/jsonrpc +``` +## Responses +``` +{"jsonrpc":"2.0","id":3,"result":null} + +``` + +## Events +``` +none +``` + +## Full Reference