1 /*
2  * Copyright (c) 2021 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_print_extension_connection.h"
17 #include "js_data_struct_converter.h"
18 #include "js_extension_context.h"
19 #include "js_runtime.h"
20 #include "js_runtime_utils.h"
21 #include "napi/native_api.h"
22 #include "napi_common_start_options.h"
23 #include "napi_common_util.h"
24 #include "napi_common_want.h"
25 #include "napi_print_utils.h"
26 #include "napi_remote_object.h"
27 #include "print_log.h"
28 #include "start_options.h"
29 #include <shared_mutex>
30 
31 using namespace OHOS::Print;
32 
33 namespace OHOS {
34 namespace AbilityRuntime {
JSPrintExtensionConnection(napi_env engine)35 JSPrintExtensionConnection::JSPrintExtensionConnection(napi_env engine) : engine_(engine) {}
36 
37 JSPrintExtensionConnection::~JSPrintExtensionConnection() = default;
38 
OnAbilityConnectDone(const AppExecFwk::ElementName & element,const sptr<IRemoteObject> & remoteObject,int resultCode)39 void JSPrintExtensionConnection::OnAbilityConnectDone(const AppExecFwk::ElementName &element,
40     const sptr<IRemoteObject> &remoteObject, int resultCode)
41 {
42     PRINT_HILOGD("OnAbilityConnectDone begin, resultCode:%{public}d", resultCode);
43     if (handler_ == nullptr) {
44         PRINT_HILOGD("handler_ nullptr");
45         return;
46     }
47     wptr<JSPrintExtensionConnection> connection = this;
48     auto task = [connection, element, remoteObject, resultCode]() {
49         sptr<JSPrintExtensionConnection> connectionSptr = connection.promote();
50         if (!connectionSptr) {
51             PRINT_HILOGD("connectionSptr nullptr");
52             return;
53         }
54         connectionSptr->HandleOnAbilityConnectDone(element, remoteObject, resultCode);
55     };
56     handler_->PostTask(task, "OnAbilityConnectDone");
57 }
58 
HandleOnAbilityConnectDone(const AppExecFwk::ElementName & element,const sptr<IRemoteObject> & remoteObject,int resultCode)59 void JSPrintExtensionConnection::HandleOnAbilityConnectDone(const AppExecFwk::ElementName &element,
60     const sptr<IRemoteObject> &remoteObject, int resultCode)
61 {
62     PRINT_HILOGD("HandleOnAbilityConnectDone begin, resultCode:%{public}d", resultCode);
63     // wrap ElementName
64     napi_value nativeElementName = OHOS::AppExecFwk::WrapElementName(engine_, element);
65 
66     // wrap RemoteObject
67     PRINT_HILOGD("OnAbilityConnectDone begin NAPI_ohos_rpc_CreateJsRemoteObject");
68     napi_value nativeRemoteObject = NAPI_ohos_rpc_CreateJsRemoteObject(engine_, remoteObject);
69     napi_value argv[] = {nativeElementName, nativeRemoteObject};
70     if (jsConnectionObject_ == nullptr) {
71         PRINT_HILOGE("jsConnectionObject_ nullptr");
72         return;
73     }
74     napi_value obj = jsConnectionObject_->GetNapiValue();
75     if (obj == nullptr) {
76         PRINT_HILOGE("Failed to get object");
77         return;
78     }
79     napi_value methodOnConnect = nullptr;
80     napi_get_named_property(engine_, obj, "onConnect", &methodOnConnect);
81     if (methodOnConnect == nullptr) {
82         PRINT_HILOGE("Failed to get onConnect from object");
83         return;
84     }
85     PRINT_HILOGD("JSPrintExtensionConnection::napi_call_function onConnect, success");
86     napi_value callResult = nullptr;
87     napi_call_function(engine_, obj, methodOnConnect, NapiPrintUtils::ARGC_TWO, argv, &callResult);
88     PRINT_HILOGD("OnAbilityConnectDone end");
89 }
90 
OnAbilityDisconnectDone(const AppExecFwk::ElementName & element,int resultCode)91 void JSPrintExtensionConnection::OnAbilityDisconnectDone(const AppExecFwk::ElementName &element, int resultCode)
92 {
93     PRINT_HILOGD("OnAbilityDisconnectDone begin, resultCode:%{public}d", resultCode);
94     if (handler_ == nullptr) {
95         PRINT_HILOGD("handler_ nullptr");
96         return;
97     }
98     wptr<JSPrintExtensionConnection> connection = this;
99     auto task = [connection, element, resultCode]() {
100         sptr<JSPrintExtensionConnection> connectionSptr = connection.promote();
101         if (!connectionSptr) {
102             PRINT_HILOGD("connectionSptr nullptr");
103             return;
104         }
105         connectionSptr->HandleOnAbilityDisconnectDone(element, resultCode);
106     };
107     handler_->PostTask(task, "OnAbilityDisconnectDone");
108 }
109 
HandleOnAbilityDisconnectDone(const AppExecFwk::ElementName & element,int resultCode)110 void JSPrintExtensionConnection::HandleOnAbilityDisconnectDone(const AppExecFwk::ElementName &element,
111     int resultCode)
112 {
113     PRINT_HILOGD("HandleOnAbilityDisconnectDone begin, resultCode:%{public}d", resultCode);
114     napi_value nativeElementName = OHOS::AppExecFwk::WrapElementName(engine_, element);
115     napi_value argv[] = {nativeElementName};
116     if (jsConnectionObject_ == nullptr) {
117         PRINT_HILOGE("jsConnectionObject_ nullptr");
118         return;
119     }
120     napi_value obj = jsConnectionObject_->GetNapiValue();
121     if (obj == nullptr) {
122         PRINT_HILOGE("Failed to get object");
123         return;
124     }
125 
126     napi_value method = nullptr;
127     napi_get_named_property(engine_, obj, "onDisconnect", &method);
128     if (method == nullptr) {
129         PRINT_HILOGE("Failed to get onDisconnect from object");
130         return;
131     }
132 
133     // release connect
134     PRINT_HILOGD("OnAbilityDisconnectDone connects_.size:%{public}zu", connects_.size());
135     std::string bundleName = element.GetBundleName();
136     std::string abilityName = element.GetAbilityName();
137     auto item = std::find_if(connects_.begin(),
138         connects_.end(),
139         [bundleName, abilityName](
140             const std::map<ConnecttionKey, sptr<JSPrintExtensionConnection>>::value_type &obj) {
141             return (bundleName == obj.first.want.GetBundle()) &&
142                    (abilityName == obj.first.want.GetElement().GetAbilityName());
143         });
144     if (item != connects_.end()) {
145         std::unique_lock<std::shared_timed_mutex> lock(managersMutex_);
146         // match bundlename && abilityname
147         connects_.erase(item);
148         PRINT_HILOGD("OnAbilityDisconnectDone erase connects_.size:%{public}zu", connects_.size());
149     }
150     PRINT_HILOGD("OnAbilityDisconnectDone napi_call_function success");
151     napi_value callResult = nullptr;
152     napi_call_function(engine_, obj, method, NapiPrintUtils::ARGC_ONE, argv, &callResult);
153 }
154 
SetJsConnectionObject(napi_value jsConnectionObject)155 void JSPrintExtensionConnection::SetJsConnectionObject(napi_value jsConnectionObject)
156 {
157     napi_ref jsRef = nullptr;
158     napi_create_reference(engine_, jsConnectionObject, 1, &jsRef);
159     jsConnectionObject_.reset(reinterpret_cast<NativeReference*>(jsRef));
160 }
161 
CallJsFailed(int32_t errorCode)162 void JSPrintExtensionConnection::CallJsFailed(int32_t errorCode)
163 {
164     PRINT_HILOGD("CallJsFailed begin");
165     if (jsConnectionObject_ == nullptr) {
166         PRINT_HILOGE("jsConnectionObject_ nullptr");
167         return;
168     }
169     napi_value obj = jsConnectionObject_->GetNapiValue();
170     if (obj == nullptr) {
171         PRINT_HILOGE("Failed to get object");
172         return;
173     }
174 
175     napi_value method = nullptr;
176     napi_get_named_property(engine_, obj, "onFailed", &method);
177     if (method == nullptr) {
178         PRINT_HILOGE("Failed to get onFailed from object");
179         return;
180     }
181 
182     napi_value result = nullptr;
183     napi_create_int32(engine_, errorCode, &result);
184     napi_value argv[] = { result };
185     PRINT_HILOGD("CallJsFailed napi_call_function success");
186     napi_value callResult = nullptr;
187     napi_call_function(engine_, obj, method, NapiPrintUtils::ARGC_ONE, argv, &callResult);
188     PRINT_HILOGD("CallJsFailed end");
189 }
190 }  // namespace AbilityRuntime
191 }  // namespace OHOS