1 /*
2 * Copyright (c) 2022-2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "js_error_observer.h"
17
18 #include <cstdint>
19
20 #include "hilog_tag_wrapper.h"
21 #include "js_runtime.h"
22 #include "js_runtime_utils.h"
23 #include "napi/native_api.h"
24
25 namespace OHOS {
26 namespace AbilityRuntime {
27 constexpr size_t ARGC_ONE = 1;
JsErrorObserver(napi_env env)28 JsErrorObserver::JsErrorObserver(napi_env env) : env_(env) {}
29
30 JsErrorObserver::~JsErrorObserver() = default;
31
OnUnhandledException(const std::string errMsg)32 void JsErrorObserver::OnUnhandledException(const std::string errMsg)
33 {
34 TAG_LOGD(AAFwkTag::JSNAPI, "called");
35 std::weak_ptr<JsErrorObserver> thisWeakPtr(shared_from_this());
36 std::shared_ptr<JsErrorObserver> jsObserver = thisWeakPtr.lock();
37 if (jsObserver) {
38 jsObserver->HandleOnUnhandledException(errMsg);
39 }
40 }
41
HandleOnUnhandledException(const std::string & errMsg)42 void JsErrorObserver::HandleOnUnhandledException(const std::string &errMsg)
43 {
44 TAG_LOGD(AAFwkTag::JSNAPI, "called");
45 auto tmpMap = jsObserverObjectMap_;
46 for (auto &item : tmpMap) {
47 napi_value value = (item.second)->GetNapiValue();
48 napi_value argv[] = { CreateJsValue(env_, errMsg) };
49 CallJsFunction(value, "onUnhandledException", argv, ARGC_ONE);
50 }
51 tmpMap = jsObserverObjectMapSync_;
52 for (auto &item : tmpMap) {
53 napi_value value = (item.second)->GetNapiValue();
54 napi_value argv[] = { CreateJsValue(env_, errMsg) };
55 CallJsFunction(value, "onUnhandledException", argv, ARGC_ONE);
56 }
57 }
58
CallJsFunction(napi_value obj,const char * methodName,napi_value const * argv,size_t argc)59 void JsErrorObserver::CallJsFunction(napi_value obj, const char* methodName, napi_value const* argv, size_t argc)
60 {
61 TAG_LOGD(AAFwkTag::JSNAPI, "call method:%{public}s", methodName);
62 if (obj == nullptr) {
63 TAG_LOGE(AAFwkTag::JSNAPI, "null obj");
64 return;
65 }
66
67 napi_value method = nullptr;
68 napi_get_named_property(env_, obj, methodName, &method);
69 if (method == nullptr) {
70 TAG_LOGE(AAFwkTag::JSNAPI, "null method");
71 return;
72 }
73 napi_value callResult = nullptr;
74 napi_call_function(env_, obj, method, argc, argv, &callResult);
75 }
76
AddJsObserverObject(const int32_t observerId,napi_value jsObserverObject,bool isSync)77 void JsErrorObserver::AddJsObserverObject(const int32_t observerId, napi_value jsObserverObject, bool isSync)
78 {
79 napi_ref ref = nullptr;
80 napi_create_reference(env_, jsObserverObject, 1, &ref);
81 if (isSync) {
82 jsObserverObjectMapSync_.emplace(
83 observerId, std::shared_ptr<NativeReference>(reinterpret_cast<NativeReference*>(ref)));
84 } else {
85 jsObserverObjectMap_.emplace(
86 observerId, std::shared_ptr<NativeReference>(reinterpret_cast<NativeReference*>(ref)));
87 }
88 }
89
RemoveJsObserverObject(const int32_t observerId,bool isSync)90 bool JsErrorObserver::RemoveJsObserverObject(const int32_t observerId, bool isSync)
91 {
92 bool result = false;
93 if (isSync) {
94 result = (jsObserverObjectMapSync_.erase(observerId) == 1);
95 } else {
96 result = (jsObserverObjectMap_.erase(observerId) == 1);
97 }
98 return result;
99 }
100
IsEmpty()101 bool JsErrorObserver::IsEmpty()
102 {
103 bool isEmpty = jsObserverObjectMap_.empty() && jsObserverObjectMapSync_.empty();
104 return isEmpty;
105 }
106
OnExceptionObject(const AppExecFwk::ErrorObject & errorObj)107 void JsErrorObserver::OnExceptionObject(const AppExecFwk::ErrorObject &errorObj)
108 {
109 TAG_LOGD(AAFwkTag::JSNAPI, "called");
110 std::weak_ptr<JsErrorObserver> thisWeakPtr(shared_from_this());
111 std::shared_ptr<JsErrorObserver> jsObserver = thisWeakPtr.lock();
112 if (jsObserver) {
113 jsObserver->HandleException(errorObj);
114 }
115 }
116
HandleException(const AppExecFwk::ErrorObject & errorObj)117 void JsErrorObserver::HandleException(const AppExecFwk::ErrorObject &errorObj)
118 {
119 TAG_LOGD(AAFwkTag::JSNAPI, "called");
120 auto tmpMap = jsObserverObjectMap_;
121 for (auto &item : tmpMap) {
122 napi_value jsObj = (item.second)->GetNapiValue();
123 napi_value jsValue[] = { CreateJsErrorObject(env_, errorObj) };
124 CallJsFunction(jsObj, "onException", jsValue, ARGC_ONE);
125 }
126 tmpMap = jsObserverObjectMapSync_;
127 for (auto &item : tmpMap) {
128 napi_value jsObj = (item.second)->GetNapiValue();
129 napi_value jsValue[] = { CreateJsErrorObject(env_, errorObj) };
130 CallJsFunction(jsObj, "onException", jsValue, ARGC_ONE);
131 }
132 }
133
CreateJsErrorObject(napi_env env,const AppExecFwk::ErrorObject & errorObj)134 napi_value JsErrorObserver::CreateJsErrorObject(napi_env env, const AppExecFwk::ErrorObject &errorObj)
135 {
136 napi_value objValue = nullptr;
137 napi_create_object(env, &objValue);
138 if (objValue == nullptr) {
139 TAG_LOGW(AAFwkTag::JSNAPI, "null obj");
140 return objValue;
141 }
142 napi_set_named_property(env, objValue, "name", CreateJsValue(env, errorObj.name));
143 napi_set_named_property(env, objValue, "message", CreateJsValue(env, errorObj.message));
144 if (!errorObj.stack.empty()) {
145 napi_set_named_property(env, objValue, "stack", CreateJsValue(env, errorObj.stack));
146 }
147
148 return objValue;
149 }
150 } // namespace AbilityRuntime
151 } // namespace OHOS
152