!9341 ui service extension双向通信发起方UIExtensionContext改动

Merge pull request !9341 from zhubingwei/bidirectioncomm-client-UIExtensionContext
This commit is contained in:
openharmony_ci 2024-07-19 07:28:45 +00:00 committed by Gitee
commit aae6a78c34
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
11 changed files with 662 additions and 17 deletions

View File

@ -39,6 +39,14 @@ class UIExtensionContext extends ExtensionContext {
return this.__context_impl__.startUIServiceExtensionAbility(want, callback);
}
connectUIServiceExtensionAbility(want, callback) {
return this.__context_impl__.connectUIServiceExtensionAbility(want, callback);
}
disconnectUIServiceExtensionAbility(proxy) {
return this.__context_impl__.disconnectUIServiceExtensionAbility(proxy);
}
openLink(link, options, callback) {
console.log('openLink');
return this.__context_impl__.openLink(link, options, callback);

View File

@ -1289,20 +1289,24 @@ config("ui_extension_public_config") {
}
ohos_shared_library("ui_extension") {
include_dirs = [ "${ability_runtime_path}/interfaces/kits/native/ability/native/ui_service_extension_ability/connection" ]
sources = [
"${ability_runtime_native_path}/ability/native/ui_extension_ability/js_embeddable_ui_ability_context.cpp",
"${ability_runtime_native_path}/ability/native/ui_extension_ability/js_ui_extension.cpp",
"${ability_runtime_native_path}/ability/native/ui_extension_ability/js_ui_extension_base.cpp",
"${ability_runtime_native_path}/ability/native/ui_extension_ability/js_ui_extension_content_session.cpp",
"${ability_runtime_native_path}/ability/native/ui_extension_ability/js_ui_extension_context.cpp",
"${ability_runtime_native_path}/ability/native/ui_extension_ability/js_uiservice_uiext_connection.cpp",
"${ability_runtime_native_path}/ability/native/ui_extension_ability/ui_extension.cpp",
"${ability_runtime_native_path}/ability/native/ui_extension_ability/ui_extension_context.cpp",
"${ability_runtime_native_path}/ability/native/ui_extension_ability/ui_extension_servicehost_stub_impl.cpp",
]
public_configs = [ ":ui_extension_public_config" ]
deps = [
":abilitykit_native",
":ui_service_extension_connection",
"${ability_runtime_innerkits_path}/ability_manager:ability_manager",
"${ability_runtime_innerkits_path}/ability_manager:ability_start_options",
"${ability_runtime_innerkits_path}/runtime:runtime",

View File

@ -576,7 +576,7 @@ napi_value JsAbilityContext::OnConnectUIServiceExtension(napi_env env, NapiCallb
}
sptr<JSUIServiceExtAbilityConnection> connection = sptr<JSUIServiceExtAbilityConnection>::MakeSptr(env);
sptr<UIAbilityServiceHostStubImpl>& stub = connection->GetServiceHostStub();
sptr<UIAbilityServiceHostStubImpl> stub = connection->GetServiceHostStub();
want.SetParam(UISERVICEHOSTPROXY_KEY, stub->AsObject());
result = nullptr;
@ -1901,11 +1901,13 @@ void JSAbilityConnection::ReleaseNativeReference(NativeReference* ref)
napi_get_uv_event_loop(env_, &loop);
if (loop == nullptr) {
TAG_LOGE(AAFwkTag::CONTEXT, "ReleaseNativeReference: failed to get uv loop.");
delete ref;
return;
}
uv_work_t *work = new (std::nothrow) uv_work_t;
if (work == nullptr) {
TAG_LOGE(AAFwkTag::CONTEXT, "ReleaseNativeReference: failed to create work.");
delete ref;
return;
}
work->data = reinterpret_cast<void *>(ref);

View File

@ -26,6 +26,8 @@
#include "js_data_struct_converter.h"
#include "js_runtime.h"
#include "js_runtime_utils.h"
#include "js_uiservice_uiext_connection.h"
#include "js_ui_service_proxy.h"
#include "napi/native_api.h"
#include "napi_common_ability.h"
#include "napi_common_want.h"
@ -37,6 +39,8 @@
#include "start_options.h"
#include "hitrace_meter.h"
#include "uri.h"
#include "ui_extension_servicehost_stub_impl.h"
#include "ui_service_extension_connection_constants.h"
namespace OHOS {
namespace AbilityRuntime {
@ -169,6 +173,17 @@ napi_value JsUIExtensionContext::StartUIServiceExtension(napi_env env, napi_call
{
GET_NAPI_INFO_AND_CALL(env, info, JsUIExtensionContext, OnStartUIServiceExtension);
}
napi_value JsUIExtensionContext::ConnectUIServiceExtension(napi_env env, napi_callback_info info)
{
GET_NAPI_INFO_AND_CALL(env, info, JsUIExtensionContext, OnConnectUIServiceExtension);
}
napi_value JsUIExtensionContext::DisconnectUIServiceExtension(napi_env env, napi_callback_info info)
{
GET_NAPI_INFO_AND_CALL(env, info, JsUIExtensionContext, OnDisconnectUIServiceExtension);
}
napi_value JsUIExtensionContext::OnStartAbility(napi_env env, NapiCallbackInfo& info)
{
HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
@ -654,6 +669,169 @@ napi_value JsUIExtensionContext::OnStartUIServiceExtension(napi_env env, NapiCal
env, CreateAsyncTaskWithLastParam(env, lastParam, nullptr, std::move(complete), &result));
return result;
}
bool JsUIExtensionContext::UnwrapConnectUIServiceExtensionParam(napi_env env, NapiCallbackInfo& info, AAFwk::Want& want)
{
if (info.argc < ARGC_TWO) {
TAG_LOGE(AAFwkTag::UISERVC_EXT, "failed, not enough params.");
ThrowTooFewParametersError(env);
return false;
}
bool unwrapResult = OHOS::AppExecFwk::UnwrapWant(env, info.argv[INDEX_ZERO], want);
if (!unwrapResult) {
TAG_LOGE(AAFwkTag::UISERVC_EXT, "failed, UnwrapWant failed");
ThrowInvalidParamError(env, "parse want error");
return false;
}
TAG_LOGI(AAFwkTag::UISERVC_EXT, "callee:%{public}s.%{public}s", want.GetBundle().c_str(),
want.GetElement().GetAbilityName().c_str());
if (!CheckTypeForNapiValue(env, info.argv[INDEX_ONE], napi_object)) {
TAG_LOGE(AAFwkTag::UISERVC_EXT, "failed, callback type incorrect");
ThrowInvalidParamError(env, "Incorrect parameter types");
return false;
}
return true;
}
bool JsUIExtensionContext::CheckConnectAlreadyExist(napi_env env, AAFwk::Want& want, napi_value callback,
napi_value& result)
{
TAG_LOGI(AAFwkTag::UISERVC_EXT, "called");
sptr<JSUIServiceUIExtConnection> connection = nullptr;
UIServiceConnection::FindUIServiceExtensionConnection(env, want, callback, connection);
if (connection == nullptr) {
TAG_LOGE(AAFwkTag::UISERVC_EXT, "connection == nullptr");
return false;
}
std::unique_ptr<NapiAsyncTask> uasyncTask = CreateAsyncTaskWithLastParam(env, nullptr, nullptr, nullptr, &result);
napi_value proxy = connection->GetProxyObject();
if (proxy == nullptr) {
TAG_LOGW(AAFwkTag::UISERVC_EXT, "can't got proxy object, wait for duplicated connect finish");
connection->AddDuplicatedPendingTask(uasyncTask);
} else {
TAG_LOGI(AAFwkTag::UISERVC_EXT, "Resolve, got proxy object");
uasyncTask->ResolveWithNoError(env, proxy);
}
return true;
}
napi_value JsUIExtensionContext::OnConnectUIServiceExtension(napi_env env, NapiCallbackInfo& info)
{
TAG_LOGI(AAFwkTag::UISERVC_EXT, "called");
AAFwk::Want want;
bool unwrapResult = UnwrapConnectUIServiceExtensionParam(env, info, want);
if (!unwrapResult) {
TAG_LOGE(AAFwkTag::UISERVC_EXT, "UnwrapConnectUIServiceExtensionParam failed");
return CreateJsUndefined(env);
}
napi_value callbackObject = nullptr;
if (info.argc > ARGC_ONE) {
callbackObject = info.argv[INDEX_ONE];
}
napi_value result = nullptr;
bool duplicated = CheckConnectAlreadyExist(env, want, callbackObject, result);
if (duplicated) {
TAG_LOGE(AAFwkTag::UISERVC_EXT, "duplicated");
return result;
}
sptr<JSUIServiceUIExtConnection> connection = sptr<JSUIServiceUIExtConnection>::MakeSptr(env);
sptr<UIExtensionServiceHostStubImpl> stub = connection->GetServiceHostStub();
want.SetParam(UISERVICEHOSTPROXY_KEY, stub->AsObject());
result = nullptr;
std::unique_ptr<NapiAsyncTask> uasyncTask = CreateAsyncTaskWithLastParam(env, nullptr, nullptr, nullptr, &result);
std::shared_ptr<NapiAsyncTask> uasyncTaskShared = std::move(uasyncTask);
if (info.argc > ARGC_ONE) {
connection->SetJsConnectionObject(callbackObject);
}
connection->SetNapiAsyncTask(uasyncTaskShared);
UIServiceConnection::AddUIServiceExtensionConnection(want, connection);
std::unique_ptr<NapiAsyncTask::CompleteCallback> complete = std::make_unique<NapiAsyncTask::CompleteCallback>(
[weak = context_, want, uasyncTaskShared, connection](
napi_env env, NapiAsyncTask& taskUseless, int32_t status) {
DoConnectUIServiceExtension(env, weak, connection, uasyncTaskShared, want);
});
napi_ref callback = nullptr;
std::unique_ptr<NapiAsyncTask::ExecuteCallback> execute = nullptr;
NapiAsyncTask::ScheduleHighQos("JsUIExtensionContext::OnConnectUIServiceExtension",
env, std::make_unique<NapiAsyncTask>(callback, std::move(execute), std::move(complete)));
return result;
}
void JsUIExtensionContext::DoConnectUIServiceExtension(napi_env env,
std::weak_ptr<UIExtensionContext> weakContext, sptr<JSUIServiceUIExtConnection> connection,
std::shared_ptr<NapiAsyncTask> uasyncTaskShared, const AAFwk::Want& want)
{
if (uasyncTaskShared == nullptr) {
return;
}
uint64_t connectId = connection->GetConnectionId();
auto context = weakContext.lock();
if (!context) {
TAG_LOGE(AAFwkTag::CONTEXT, "Connect ability failed, context is released.");
uasyncTaskShared->Reject(env, CreateJsError(env, AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT));
UIServiceConnection::RemoveUIServiceExtensionConnection(connectId);
return;
}
auto innerErrorCode = context->ConnectAbility(want, connection);
AbilityErrorCode errcode = AbilityRuntime::GetJsErrorCodeByNativeError(innerErrorCode);
if (errcode != AbilityErrorCode::ERROR_OK) {
TAG_LOGE(AAFwkTag::UISERVC_EXT, "ConnectAbility failed, errcode is %{public}d.", errcode);
uasyncTaskShared->Reject(env, CreateJsError(env, errcode));
UIServiceConnection::RemoveUIServiceExtensionConnection(connectId);
}
}
napi_value JsUIExtensionContext::OnDisconnectUIServiceExtension(napi_env env, NapiCallbackInfo& info)
{
if (info.argc < ARGC_ONE) {
TAG_LOGE(AAFwkTag::UISERVC_EXT, "failed, not enough params.");
ThrowTooFewParametersError(env);
return CreateJsUndefined(env);
}
AAFwk::JsUIServiceProxy* proxy = nullptr;
napi_status status = napi_unwrap(env, info.argv[INDEX_ZERO], reinterpret_cast<void**>(&proxy));
if (status != napi_ok || proxy == nullptr) {
TAG_LOGE(AAFwkTag::UISERVC_EXT, "napi_unwrap err or proxy == nullptr");
ThrowInvalidParamError(env, "Parameter verification failed");
return CreateJsUndefined(env);
}
int64_t connectId = proxy->GetConnectionId();
AAFwk::Want want;
sptr<JSUIServiceUIExtConnection> connection = nullptr;
UIServiceConnection::FindUIServiceExtensionConnection(connectId, want, connection);
TAG_LOGI(AAFwkTag::UISERVC_EXT, "connection:%{public}d.", static_cast<int32_t>(connectId));
NapiAsyncTask::CompleteCallback complete =
[weak = context_, want, connectId, connection](
napi_env env, NapiAsyncTask& task, int32_t status) {
auto context = weak.lock();
if (!context) {
TAG_LOGW(AAFwkTag::UISERVC_EXT, "OnDisconnectUIServiceExtension context is released");
task.Reject(env, CreateJsError(env, AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT));
UIServiceConnection::RemoveUIServiceExtensionConnection(connectId);
} else if (!connection) {
TAG_LOGW(AAFwkTag::UISERVC_EXT, "connection nullptr");
task.Reject(env, CreateJsError(env, AbilityErrorCode::ERROR_CODE_INNER));
UIServiceConnection::RemoveUIServiceExtensionConnection(connectId);
} else {
TAG_LOGI(AAFwkTag::UISERVC_EXT, "context->DisconnectAbility");
context->DisconnectAbility(want, connection);
task.ResolveWithNoError(env, CreateJsUndefined(env));
}
};
napi_value result = nullptr;
NapiAsyncTask::Schedule("JsUIExtensionContext::OnDisconnectUIServiceExtension",
env, CreateAsyncTaskWithLastParam(env, nullptr, nullptr, std::move(complete), &result));
return result;
}
napi_value JsUIExtensionContext::OnReportDrawnCompleted(napi_env env, NapiCallbackInfo& info)
{
TAG_LOGD(AAFwkTag::UI_EXT, "called.");
@ -860,6 +1038,8 @@ napi_value JsUIExtensionContext::CreateJsUIExtensionContext(napi_env env,
BindNativeFunction(env, objValue, "reportDrawnCompleted", moduleName, ReportDrawnCompleted);
BindNativeFunction(env, objValue, "openAtomicService", moduleName, OpenAtomicService);
BindNativeFunction(env, objValue, "startUIServiceExtensionAbility", moduleName, StartUIServiceExtension);
BindNativeFunction(env, objValue, "connectUIServiceExtensionAbility", moduleName, ConnectUIServiceExtension);
BindNativeFunction(env, objValue, "disconnectUIServiceExtensionAbility", moduleName, DisconnectUIServiceExtension);
return objValue;
}
@ -890,41 +1070,53 @@ JSUIExtensionConnection::JSUIExtensionConnection(napi_env env) : env_(env) {}
JSUIExtensionConnection::~JSUIExtensionConnection()
{
if (jsConnectionObject_ == nullptr) {
ReleaseNativeReference(jsConnectionObject_.release());
}
void JSUIExtensionConnection::ReleaseNativeReference(NativeReference* ref)
{
if (ref == nullptr) {
TAG_LOGE(AAFwkTag::CONTEXT, "ReleaseNativeReference: ref == nullptr");
return;
}
uv_loop_t *loop = nullptr;
napi_get_uv_event_loop(env_, &loop);
if (loop == nullptr) {
TAG_LOGE(AAFwkTag::CONTEXT, "ReleaseNativeReference: failed to get uv loop.");
delete ref;
return;
}
uv_work_t *work = new (std::nothrow) uv_work_t;
if (work == nullptr) {
TAG_LOGE(AAFwkTag::CONTEXT, "ReleaseNativeReference: failed to create work.");
delete ref;
return;
}
work->data = reinterpret_cast<void *>(jsConnectionObject_.release());
work->data = reinterpret_cast<void *>(ref);
int ret = uv_queue_work(loop, work, [](uv_work_t *work) {},
[](uv_work_t *work, int status) {
[](uv_work_t *work, int status) {
if (work == nullptr) {
TAG_LOGE(AAFwkTag::CONTEXT, "ReleaseNativeReference: work is nullptr.");
return;
}
if (work->data == nullptr) {
TAG_LOGE(AAFwkTag::CONTEXT, "ReleaseNativeReference: data is nullptr.");
delete work;
work = nullptr;
return;
}
delete reinterpret_cast<NativeReference *>(work->data);
work->data = nullptr;
NativeReference *refPtr = reinterpret_cast<NativeReference *>(work->data);
delete refPtr;
refPtr = nullptr;
delete work;
work = nullptr;
});
if (ret != 0) {
delete reinterpret_cast<NativeReference *>(work->data);
work->data = nullptr;
delete work;
work = nullptr;
delete ref;
if (work != nullptr) {
delete work;
work = nullptr;
}
}
}
@ -1069,5 +1261,32 @@ void JSUIExtensionConnection::CallJsFailed(int32_t errorCode)
TAG_LOGD(AAFwkTag::UI_EXT, "CallJsFailed end");
}
napi_value JSUIExtensionConnection::CallObjectMethod(const char* name, napi_value const *argv, size_t argc)
{
TAG_LOGD(AAFwkTag::CONTEXT, "name:%{public}s", name);
if (!jsConnectionObject_) {
TAG_LOGW(AAFwkTag::CONTEXT, "Not found jsConnectionObject_");
return nullptr;
}
HandleScope handleScope(env_);
napi_value obj = jsConnectionObject_->GetNapiValue();
if (!CheckTypeForNapiValue(env_, obj, napi_object)) {
TAG_LOGE(AAFwkTag::CONTEXT, "Failed to get jsConnectionObject_ object");
return nullptr;
}
napi_value method = nullptr;
napi_get_named_property(env_, obj, name, &method);
if (!CheckTypeForNapiValue(env_, method, napi_function)) {
TAG_LOGE(AAFwkTag::CONTEXT, "Failed to get '%{public}s' from jsConnectionObject_ object", name);
return nullptr;
}
napi_value result = nullptr;
napi_call_function(env_, obj, method, argc, argv, &result);
TAG_LOGD(AAFwkTag::CONTEXT, "CallFunction(%{public}s) ok", name);
return result;
}
} // namespace AbilityRuntime
} // namespace OHOS

View File

@ -0,0 +1,259 @@
/*
* Copyright (c) 2024 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 "js_uiservice_uiext_connection.h"
#include "ability_business_error.h"
#include "hilog_tag_wrapper.h"
#include "js_error_utils.h"
#include "js_ui_service_proxy.h"
#include "napi_common_want.h"
#include "ui_extension_servicehost_stub_impl.h"
namespace OHOS {
namespace AbilityRuntime {
constexpr size_t ARGC_ONE = 1;
namespace UIServiceConnection {
static std::map<UIExtensionConnectionKey, sptr<JSUIServiceUIExtConnection>, key_compare> gUiServiceExtConnects;
static std::recursive_mutex gUiServiceExtConnectsLock;
static int64_t gUiServiceExtConnectSn = 0;
void AddUIServiceExtensionConnection(AAFwk::Want& want, sptr<JSUIServiceUIExtConnection>& connection)
{
std::lock_guard<std::recursive_mutex> lock(gUiServiceExtConnectsLock);
UIExtensionConnectionKey key;
key.id = gUiServiceExtConnectSn;
key.want = want;
connection->SetConnectionId(key.id);
gUiServiceExtConnects.emplace(key, connection);
if (gUiServiceExtConnectSn < INT32_MAX) {
gUiServiceExtConnectSn++;
} else {
gUiServiceExtConnectSn = 0;
}
}
void RemoveUIServiceExtensionConnection(const int64_t& connectId)
{
std::lock_guard<std::recursive_mutex> lock(gUiServiceExtConnectsLock);
auto item = std::find_if(gUiServiceExtConnects.begin(), gUiServiceExtConnects.end(),
[&connectId](const auto &obj) {
return connectId == obj.first.id;
});
if (item != gUiServiceExtConnects.end()) {
TAG_LOGI(AAFwkTag::UI_EXT, "found, erase");
gUiServiceExtConnects.erase(item);
} else {
TAG_LOGI(AAFwkTag::UI_EXT, "not found");
}
TAG_LOGI(AAFwkTag::CONTEXT, "Connects new size:%{public}zu", gUiServiceExtConnects.size());
}
void FindUIServiceExtensionConnection(const int64_t& connectId, AAFwk::Want& want,
sptr<JSUIServiceUIExtConnection>& connection)
{
std::lock_guard<std::recursive_mutex> lock(gUiServiceExtConnectsLock);
TAG_LOGI(AAFwkTag::UI_EXT, "connection:%{public}d", static_cast<int32_t>(connectId));
auto item = std::find_if(gUiServiceExtConnects.begin(), gUiServiceExtConnects.end(),
[&connectId](const auto &obj) {
return connectId == obj.first.id;
});
if (item != gUiServiceExtConnects.end()) {
want = item->first.want;
connection = item->second;
TAG_LOGI(AAFwkTag::UI_EXT, "found");
} else {
TAG_LOGI(AAFwkTag::UI_EXT, "not found");
}
}
void FindUIServiceExtensionConnection(napi_env env, AAFwk::Want& want, napi_value callback,
sptr<JSUIServiceUIExtConnection>& connection)
{
std::lock_guard<std::recursive_mutex> lock(gUiServiceExtConnectsLock);
auto item = std::find_if(gUiServiceExtConnects.begin(), gUiServiceExtConnects.end(),
[&want, env, callback](const auto &obj) {
bool wantEquals = (obj.first.want.GetElement() == want.GetElement());
std::unique_ptr<NativeReference>& tempCallbackPtr = obj.second->GetJsConnectionObject();
bool callbackObjectEquals =
JSUIServiceUIExtConnection::IsJsCallbackObjectEquals(env, tempCallbackPtr, callback);
return wantEquals && callbackObjectEquals;
});
if (item == gUiServiceExtConnects.end()) {
return;
}
connection = item->second;
}
}
JSUIServiceUIExtConnection::JSUIServiceUIExtConnection(napi_env env) : JSUIExtensionConnection(env)
{
TAG_LOGI(AAFwkTag::UISERVC_EXT, "JSUIServiceUIExtConnection");
wptr<JSUIServiceUIExtConnection> weakthis = this;
serviceHostStub_ = sptr<UIExtensionServiceHostStubImpl>::MakeSptr(weakthis);
}
JSUIServiceUIExtConnection::~JSUIServiceUIExtConnection()
{
TAG_LOGI(AAFwkTag::UISERVC_EXT, "~JSUIServiceUIExtConnection");
serviceHostStub_ = nullptr;
napiAsyncTask_.reset();
ReleaseNativeReference(serviceProxyObject_.release());
}
void JSUIServiceUIExtConnection::HandleOnAbilityConnectDone(
const AppExecFwk::ElementName &element, const sptr<IRemoteObject> &remoteObject, int resultCode)
{
if (napiAsyncTask_ != nullptr) {
TAG_LOGI(AAFwkTag::UISERVC_EXT, "HandleOnAbilityConnectDone, CreateJsUIServiceProxy");
sptr<UIExtensionServiceHostStubImpl> hostStub = GetServiceHostStub();
sptr<IRemoteObject> hostProxy = nullptr;
if (hostStub != nullptr) {
hostProxy = hostStub->AsObject();
}
napi_value proxy = AAFwk::JsUIServiceProxy::CreateJsUIServiceProxy(env_, remoteObject,
connectionId_, hostProxy);
SetProxyObject(proxy);
napiAsyncTask_->ResolveWithNoError(env_, proxy);
ResolveDuplicatedPendingTask(env_, proxy);
} else {
TAG_LOGE(AAFwkTag::UISERVC_EXT, "HandleOnAbilityConnectDone, napiAsyncTask_ null");
}
napiAsyncTask_.reset();
}
void JSUIServiceUIExtConnection::HandleOnAbilityDisconnectDone(const AppExecFwk::ElementName &element,
int resultCode)
{
if (napiAsyncTask_ != nullptr) {
napi_value innerError = CreateJsError(env_, AbilityErrorCode::ERROR_CODE_INNER);
napiAsyncTask_->Reject(env_, innerError);
RejectDuplicatedPendingTask(env_, innerError);
napiAsyncTask_ = nullptr;
}
CallJsOnDisconnect();
SetProxyObject(nullptr);
RemoveConnectionObject();
duplicatedPendingTaskList_.clear();
UIServiceConnection::RemoveUIServiceExtensionConnection(connectionId_);
}
void JSUIServiceUIExtConnection::SetNapiAsyncTask(std::shared_ptr<NapiAsyncTask>& task)
{
napiAsyncTask_ = task;
}
void JSUIServiceUIExtConnection::AddDuplicatedPendingTask(std::unique_ptr<NapiAsyncTask>& task)
{
duplicatedPendingTaskList_.push_back(std::move(task));
}
void JSUIServiceUIExtConnection::ResolveDuplicatedPendingTask(napi_env env, napi_value proxy)
{
TAG_LOGI(AAFwkTag::UISERVC_EXT, "called, size %{public}zu", duplicatedPendingTaskList_.size());
for (auto &task : duplicatedPendingTaskList_) {
if (task != nullptr) {
task->ResolveWithNoError(env, proxy);
}
}
duplicatedPendingTaskList_.clear();
}
void JSUIServiceUIExtConnection::RejectDuplicatedPendingTask(napi_env env, napi_value error)
{
TAG_LOGI(AAFwkTag::UISERVC_EXT, "called, size %{public}zu", duplicatedPendingTaskList_.size());
for (auto &task : duplicatedPendingTaskList_) {
if (task != nullptr) {
task->Reject(env, error);
}
}
duplicatedPendingTaskList_.clear();
}
void JSUIServiceUIExtConnection::SetProxyObject(napi_value proxy)
{
TAG_LOGI(AAFwkTag::UISERVC_EXT, "SetProxyObject");
serviceProxyObject_.reset();
if (proxy != nullptr) {
napi_ref ref = nullptr;
napi_create_reference(env_, proxy, 1, &ref);
serviceProxyObject_ = std::unique_ptr<NativeReference>(reinterpret_cast<NativeReference*>(ref));
}
}
napi_value JSUIServiceUIExtConnection::GetProxyObject()
{
if (serviceProxyObject_ == nullptr) {
return nullptr;
}
return serviceProxyObject_->GetNapiValue();
}
int32_t JSUIServiceUIExtConnection::OnSendData(OHOS::AAFwk::WantParams &data)
{
wptr<JSUIServiceUIExtConnection> connection = this;
std::unique_ptr<NapiAsyncTask::CompleteCallback> complete = std::make_unique<NapiAsyncTask::CompleteCallback>
([connection, wantParams = data](napi_env env, NapiAsyncTask &task, int32_t status) {
sptr<JSUIServiceUIExtConnection> connectionSptr = connection.promote();
if (!connectionSptr) {
TAG_LOGE(AAFwkTag::UISERVC_EXT, "connectionSptr nullptr");
return;
}
connectionSptr->HandleOnSendData(wantParams);
});
napi_ref callback = nullptr;
std::unique_ptr<NapiAsyncTask::ExecuteCallback> execute = nullptr;
NapiAsyncTask::Schedule("JSUIServiceUIExtConnection::SendData",
env_, std::make_unique<NapiAsyncTask>(callback, std::move(execute), std::move(complete)));
return static_cast<int32_t>(AbilityErrorCode::ERROR_OK);
}
void JSUIServiceUIExtConnection::HandleOnSendData(const OHOS::AAFwk::WantParams &data)
{
napi_value argv[] = { AppExecFwk::CreateJsWantParams(env_, data) };
CallObjectMethod("onData", argv, ARGC_ONE);
}
void JSUIServiceUIExtConnection::CallJsOnDisconnect()
{
TAG_LOGI(AAFwkTag::UISERVC_EXT, "called");
CallObjectMethod("onDisconnect", nullptr, 0);
}
bool JSUIServiceUIExtConnection::IsJsCallbackObjectEquals(napi_env env,
std::unique_ptr<NativeReference> &callback, napi_value value)
{
if (value == nullptr || callback == nullptr) {
return callback.get() == reinterpret_cast<NativeReference*>(value);
}
auto object = callback->GetNapiValue();
if (object == nullptr) {
TAG_LOGE(AAFwkTag::UISERVC_EXT, "Failed to get object.");
return false;
}
bool result = false;
if (napi_strict_equals(env, object, value, &result) != napi_ok) {
TAG_LOGE(AAFwkTag::UISERVC_EXT, "Object does not match value.");
return false;
}
return result;
}
}
}

View File

@ -0,0 +1,40 @@
/*
* Copyright (c) 2024 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 "ui_extension_servicehost_stub_impl.h"
#include "ability_business_error.h"
#include "js_uiservice_uiext_connection.h"
namespace OHOS {
namespace AbilityRuntime {
UIExtensionServiceHostStubImpl::UIExtensionServiceHostStubImpl(wptr<JSUIServiceUIExtConnection> conn)
:conn_(conn)
{
}
int32_t UIExtensionServiceHostStubImpl::SendData(OHOS::AAFwk::WantParams &data)
{
sptr<JSUIServiceUIExtConnection> conn = conn_.promote();
if (conn != nullptr) {
return conn->OnSendData(data);
}
return static_cast<int32_t>(AbilityErrorCode::ERROR_CODE_INNER);
}
}
}

View File

@ -38,7 +38,7 @@ public:
virtual void HandleOnAbilityConnectDone(
const AppExecFwk::ElementName &element, const sptr<IRemoteObject> &remoteObject, int resultCode) override;
virtual void HandleOnAbilityDisconnectDone(const AppExecFwk::ElementName &element, int resultCode) override;
sptr<UIAbilityServiceHostStubImpl>& GetServiceHostStub() { return serviceHostStub_; }
sptr<UIAbilityServiceHostStubImpl> GetServiceHostStub() { return serviceHostStub_; }
void SetProxyObject(napi_value proxy);
napi_value GetProxyObject();
void SetNapiAsyncTask(std::shared_ptr<NapiAsyncTask>& task);

View File

@ -26,6 +26,7 @@ namespace OHOS {
namespace AbilityRuntime {
struct NapiCallbackInfo;
class JsEmbeddableUIAbilityContext;
class JSUIServiceUIExtConnection;
class JsUIExtensionContext {
public:
@ -44,6 +45,8 @@ public:
static napi_value ReportDrawnCompleted(napi_env env, napi_callback_info info);
static napi_value OpenAtomicService(napi_env env, napi_callback_info info);
static napi_value StartUIServiceExtension(napi_env env, napi_callback_info info);
static napi_value ConnectUIServiceExtension(napi_env env, napi_callback_info info);
static napi_value DisconnectUIServiceExtension(napi_env env, napi_callback_info info);
protected:
virtual napi_value OnStartAbility(napi_env env, NapiCallbackInfo& info);
@ -56,6 +59,13 @@ protected:
virtual napi_value OnReportDrawnCompleted(napi_env env, NapiCallbackInfo& info);
virtual napi_value OnOpenAtomicService(napi_env env, NapiCallbackInfo& info);
virtual napi_value OnStartUIServiceExtension(napi_env env, NapiCallbackInfo& info);
bool UnwrapConnectUIServiceExtensionParam(napi_env env, NapiCallbackInfo& info, AAFwk::Want& want);
bool CheckConnectAlreadyExist(napi_env env, AAFwk::Want& want, napi_value callback, napi_value& result);
virtual napi_value OnConnectUIServiceExtension(napi_env env, NapiCallbackInfo& info);
static void DoConnectUIServiceExtension(napi_env env,
std::weak_ptr<UIExtensionContext> weakContext, sptr<JSUIServiceUIExtConnection> connection,
std::shared_ptr<NapiAsyncTask> uasyncTaskShared, const AAFwk::Want& want);
virtual napi_value OnDisconnectUIServiceExtension(napi_env env, NapiCallbackInfo& info);
void SetCallbackForTerminateWithResult(int32_t resultCode, AAFwk::Want& want,
NapiAsyncTask::CompleteCallback& complete);
@ -83,18 +93,21 @@ class JSUIExtensionConnection : public AbilityConnectCallback {
public:
explicit JSUIExtensionConnection(napi_env env);
~JSUIExtensionConnection();
void ReleaseNativeReference(NativeReference* ref);
void OnAbilityConnectDone(
const AppExecFwk::ElementName &element, const sptr<IRemoteObject> &remoteObject, int resultCode) override;
void OnAbilityDisconnectDone(const AppExecFwk::ElementName &element, int resultCode) override;
void HandleOnAbilityConnectDone(
virtual void HandleOnAbilityConnectDone(
const AppExecFwk::ElementName &element, const sptr<IRemoteObject> &remoteObject, int resultCode);
void HandleOnAbilityDisconnectDone(const AppExecFwk::ElementName &element, int resultCode);
virtual void HandleOnAbilityDisconnectDone(const AppExecFwk::ElementName &element, int resultCode);
void SetJsConnectionObject(napi_value jsConnectionObject);
std::unique_ptr<NativeReference>& GetJsConnectionObject() { return jsConnectionObject_; }
void RemoveConnectionObject();
void CallJsFailed(int32_t errorCode);
napi_value CallObjectMethod(const char* name, napi_value const *argv, size_t argc);
void SetConnectionId(int64_t id);
int64_t GetConnectionId();
private:
protected:
napi_env env_ = nullptr;
std::unique_ptr<NativeReference> jsConnectionObject_ = nullptr;
int64_t connectionId_ = -1;

View File

@ -0,0 +1,62 @@
/*
* Copyright (c) 2024 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_UISERVICE_UIEXT_CONNECTION_H
#define OHOS_ABILITY_RUNTIME_UISERVICE_UIEXT_CONNECTION_H
#include "js_ui_extension_context.h"
#include "ui_service_host_stub.h"
namespace OHOS {
namespace AbilityRuntime {
namespace UIServiceConnection {
void AddUIServiceExtensionConnection(AAFwk::Want& want, sptr<JSUIServiceUIExtConnection>& connection);
void RemoveUIServiceExtensionConnection(const int64_t& connectId);
void FindUIServiceExtensionConnection(const int64_t& connectId, AAFwk::Want& want,
sptr<JSUIServiceUIExtConnection>& connection);
void FindUIServiceExtensionConnection(napi_env env, AAFwk::Want& want, napi_value callback,
sptr<JSUIServiceUIExtConnection>& connection);
}
class UIExtensionServiceHostStubImpl;
class JSUIServiceUIExtConnection : public JSUIExtensionConnection {
public:
JSUIServiceUIExtConnection(napi_env env);
~JSUIServiceUIExtConnection();
virtual void HandleOnAbilityConnectDone(
const AppExecFwk::ElementName &element, const sptr<IRemoteObject> &remoteObject, int resultCode) override;
virtual void HandleOnAbilityDisconnectDone(const AppExecFwk::ElementName &element, int resultCode) override;
sptr<UIExtensionServiceHostStubImpl> GetServiceHostStub() { return serviceHostStub_; }
void SetProxyObject(napi_value proxy);
napi_value GetProxyObject();
void SetNapiAsyncTask(std::shared_ptr<NapiAsyncTask>& task);
void AddDuplicatedPendingTask(std::unique_ptr<NapiAsyncTask>& task);
void ResolveDuplicatedPendingTask(napi_env env, napi_value proxy);
void RejectDuplicatedPendingTask(napi_env env, napi_value error);
int32_t OnSendData(OHOS::AAFwk::WantParams &data);
void HandleOnSendData(const OHOS::AAFwk::WantParams &data);
void CallJsOnDisconnect();
static bool IsJsCallbackObjectEquals(napi_env env, std::unique_ptr<NativeReference>& callback, napi_value value);
private:
sptr<UIExtensionServiceHostStubImpl> serviceHostStub_;
std::unique_ptr<NativeReference> serviceProxyObject_;
std::shared_ptr<NapiAsyncTask> napiAsyncTask_;
std::vector<std::unique_ptr<NapiAsyncTask>> duplicatedPendingTaskList_;
};
}
}
#endif

View File

@ -0,0 +1,38 @@
/*
* Copyright (c) 2024 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_UI_EXTENSION_SERVICEHOST_STUB_IMPL_H
#define OHOS_ABILITY_RUNTIME_UI_EXTENSION_SERVICEHOST_STUB_IMPL_H
#include "js_ui_extension_context.h"
#include "ui_service_host_stub.h"
namespace OHOS {
namespace AbilityRuntime {
class UIExtensionServiceHostStubImpl : public AAFwk::UIServiceHostStub {
public:
UIExtensionServiceHostStubImpl(wptr<JSUIServiceUIExtConnection> conn);
~UIExtensionServiceHostStubImpl() = default;
virtual int32_t SendData(OHOS::AAFwk::WantParams &data) override;
protected:
wptr<JSUIServiceUIExtConnection> conn_;
};
}
}
#endif

View File

@ -8203,7 +8203,7 @@ int AbilityManagerService::CheckPermissionForUIService(const Want &want, const A
int result = AAFwk::PermissionVerification::GetInstance()->CheckCallServiceExtensionPermission(verificationInfo);
if (result != ERR_OK) {
TAG_LOGE(AAFwkTag::ABILITYMGR, "Do not have permission to start UIServiceExtension");
TAG_LOGE(AAFwkTag::ABILITYMGR, "CheckCallServiceExtensionPermission failed");
return result;
}