* 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 <sstream>
#include "platform_view_resource.h"
#include "base/log/log.h"
namespace OHOS::Ace {
const char PLATFORM_VIEW_PARAM_NONE[] = "";
const char PLATFORM_VIEW_PARAM_AND[] = "#HWJS-&-#";
const char PLATFORM_VIEW_PARAM_VALUE[] = "value";
const char PLATFORM_VIEW_PARAM_EQUALS[] = "#HWJS-=-#";
const char PLATFORM_VIEW_PARAM_BEGIN[] = "#HWJS-?-#";
const char PLATFORM_VIEW_METHOD[] = "method";
const char PLATFORM_VIEW_EVENT[] = "event";
const char PLATFORM_VIEW_RESULT_FAIL[] = "fail";
void PlatformViewResource::Release(const std::function<void(bool)>& onRelease)
{
if (id_ == PLATFORM_VIEW_INVALID_ID) {
return;
}
auto context = context_.Upgrade();
if (!context) {
LOGE("fail to release resource due to context is null");
return;
}
auto resRegister = context->GetPlatformResRegister();
auto platformTaskExecutor = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::PLATFORM);
auto weakRes = AceType::WeakClaim(AceType::RawPtr(resRegister));
auto releaseTask = [weak = AceType::WeakClaim(this), weakRes, onRelease] {
auto resource = weak.Upgrade();
auto resRegister = weakRes.Upgrade();
if (resource == nullptr || resRegister == nullptr) {
LOGE("resource or resRegister is nullptr");
return;
}
bool ret = resRegister->ReleaseResource(resource->hash_);
if (ret) {
resource->id_ = PLATFORM_VIEW_INVALID_ID;
resource->hash_.clear();
}
if (onRelease) {
onRelease(ret);
}
};
if (platformTaskExecutor.IsRunOnCurrentThread()) {
releaseTask();
} else {
platformTaskExecutor.PostTask(releaseTask, "ArkUI-XPlatformViewResourceRelease");
}
}
double PlatformViewResource::GetDoubleParam(const std::string& param, const std::string& name) const
{
size_t len = name.length();
size_t pos = param.find(name);
double result = 0.0;
if (pos != std::string::npos) {
std::stringstream ss;
ss << param.substr(pos + 1 + len);
ss >> result;
}
return result;
}
int32_t PlatformViewResource::GetIntParam(const std::string& param, const std::string& name) const
{
size_t len = name.length();
size_t pos = param.find(name);
int32_t result = 0;
if (pos != std::string::npos) {
std::stringstream ss;
ss << param.substr(pos + 1 + len);
ss >> result;
}
return result;
}
int64_t PlatformViewResource::GetInt64Param(const std::string& param, const std::string& name) const
{
size_t len = name.length();
size_t pos = param.find(name);
int64_t result = 0;
if (pos != std::string::npos) {
std::stringstream ss;
ss << param.substr(pos + 1 + len);
ss >> result;
}
return result;
}
void PlatformViewResource::GetFloatArrayParam(
const std::string& param, const std::string& name, std::vector<float>& matrix) const
{
size_t len = name.length();
size_t pos = param.find(name);
matrix.clear();
if (pos == std::string::npos) {
return;
}
std::string data = param.substr(pos + 1 + len);
pos = data.find("[");
if (pos == std::string::npos) {
return;
}
do {
std::stringstream ss;
ss << data.substr(pos + 1);
float tmp = 0;
ss >> tmp;
matrix.emplace_back(tmp);
data = data.substr(pos + 1);
pos = data.find(",");
if (pos == std::string::npos) {
return;
}
} while (1);
return;
}
std::map<std::string, std::string> PlatformViewResource::ParseMapFromString(const std::string& param)
{
size_t equalsLen = sizeof(PLATFORM_VIEW_PARAM_EQUALS) - 1;
size_t andLen = sizeof(PLATFORM_VIEW_PARAM_EQUALS) - 1;
size_t totalLen = param.length();
size_t index = 0;
std::map<std::string, std::string> result;
while (index < totalLen) {
size_t end = param.find(PLATFORM_VIEW_PARAM_AND, index);
if (end == std::string::npos) {
end = totalLen;
}
size_t mid = param.find(PLATFORM_VIEW_PARAM_EQUALS, index);
if (mid == std::string::npos) {
index = end + andLen;
continue;
}
std::string key = param.substr(index, mid - index);
std::string value = param.substr(mid + equalsLen, end - mid - equalsLen);
result[key] = value;
index = end + andLen;
}
return result;
}
std::string PlatformViewResource::MakeResourceHash() const
{
std::stringstream hashCode;
hashCode << type_ << "@" << id_;
return hashCode.str();
}
std::string PlatformViewResource::MakeEventHash(const std::string& event) const
{
std::string eventHash = hash_;
eventHash += std::string(PLATFORM_VIEW_EVENT);
eventHash += std::string(PLATFORM_VIEW_PARAM_EQUALS);
eventHash += event;
eventHash += std::string(PLATFORM_VIEW_PARAM_BEGIN);
return eventHash;
}
std::string PlatformViewResource::MakeMethodHash(const std::string& method) const
{
std::string methodHash = hash_;
methodHash += std::string(PLATFORM_VIEW_METHOD);
methodHash += std::string(PLATFORM_VIEW_PARAM_EQUALS);
methodHash += method;
methodHash += std::string(PLATFORM_VIEW_PARAM_BEGIN);
return methodHash;
}
bool PlatformViewResource::IsResultSuccess(const std::string& result) const
{
size_t pos = result.find(PLATFORM_VIEW_RESULT_FAIL);
return pos != 0;
}
void PlatformViewResource::OnError(const std::string& errorCode, const std::string& errorMsg)
{
if (onError_) {
onError_(errorCode, errorMsg);
}
}
void PlatformViewResource::CallResRegisterMethod(
const std::string& method, const std::string& param, const std::function<void(std::string&)>& callback)
{
if (method.empty()) {
return;
}
auto context = context_.Upgrade();
if (!context) {
LOGE("fail to get context to call res register method");
return;
}
auto resRegister = context->GetPlatformResRegister();
auto platformTaskExecutor = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::PLATFORM);
auto weakRes = AceType::WeakClaim(AceType::RawPtr(resRegister));
platformTaskExecutor.PostTask(
[method, param, weakRes, callback] {
auto resRegister = weakRes.Upgrade();
if (resRegister == nullptr) {
LOGE("resRegister is nullptr");
return;
}
std::string result;
resRegister->OnMethodCall(method, param, result);
if (callback) {
callback(result);
}
},
"ArkUI-XPlatformViewResourceCallResRegisterMethod");
}
void PlatformViewResource::CallSyncResRegisterMethod(
const Method& method, const std::string& param, const std::function<void(std::string&)>& callback)
{
if (method.empty()) {
return;
}
auto context = context_.Upgrade();
if (!context) {
LOGE("fail to get context to call res register method");
return;
}
auto resRegister = context->GetPlatformResRegister();
std::string result;
if (!resRegister) {
LOGE("fail to get resRegister to call res register method");
return;
}
resRegister->OnMethodCall(method, param, result);
if (callback) {
callback(result);
}
}
}