• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2025 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 "screen_capture_monitor_napi.h"
17 #include "media_dfx.h"
18 #include "media_log.h"
19 #include <refbase.h>
20 #include "media_errors.h"
21 #include "recorder_napi_utils.h"
22 
23 namespace {
24     constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_RECORDER, "ScreenCaptureMonitorNapi"};
25 }
26 
27 namespace OHOS {
28 namespace Media {
29 thread_local napi_ref ScreenCaptureMonitorNapi::constructor_ = nullptr;
30 const std::string CLASS_NAME = "ScreenCaptureMonitor";
31 
SignError(ScreenCaptureMonitorAsyncContext * asyncCtx,int32_t code,const std::string & param1,const std::string & param2,const std::string & add="")32 static void SignError(ScreenCaptureMonitorAsyncContext *asyncCtx, int32_t code,
33     const std::string &param1, const std::string &param2, const std::string &add = "")
34 {
35     std::string message = MSExtErrorAPI9ToString(static_cast<MediaServiceExtErrCodeAPI9>(code), param1, param2) + add;
36     asyncCtx->SignError(code, message);
37 }
38 
ScreenCaptureMonitorNapi()39 ScreenCaptureMonitorNapi::ScreenCaptureMonitorNapi()
40 {
41     MEDIA_LOGI("0x%{public}06" PRIXPTR "Instances create", FAKE_POINTER(this));
42 }
43 
~ScreenCaptureMonitorNapi()44 ScreenCaptureMonitorNapi::~ScreenCaptureMonitorNapi()
45 {
46     MEDIA_LOGI("0x%{public}06" PRIXPTR "Instances destroy", FAKE_POINTER(this));
47 }
48 
Init(napi_env env,napi_value exports)49 napi_value ScreenCaptureMonitorNapi::Init(napi_env env, napi_value exports)
50 {
51     MEDIA_LOGI("JS Init Start");
52     napi_property_descriptor staticProperty[] = {
53         DECLARE_NAPI_STATIC_FUNCTION("getScreenCaptureMonitor", JsGetScreenCaptureMonitor),
54     };
55 
56     napi_property_descriptor properties[] = {
57         DECLARE_NAPI_FUNCTION("on", JsSetEventCallback),
58         DECLARE_NAPI_FUNCTION("off", JsCancelEventCallback),
59 
60         DECLARE_NAPI_GETTER("isSystemScreenRecorderWorking", JsIsSystemScreenRecorderWorking),
61     };
62 
63     napi_value constructor = nullptr;
64     napi_status status = napi_define_class(env, CLASS_NAME.c_str(), NAPI_AUTO_LENGTH, Constructor, nullptr,
65                                            sizeof(properties) / sizeof(properties[0]), properties, &constructor);
66     CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "Failed to define ScreenCaptureMonitor class");
67 
68     status = napi_create_reference(env, constructor, 1, &constructor_);
69     CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "Failed to create reference of constructor");
70 
71     status = napi_set_named_property(env, exports, CLASS_NAME.c_str(), constructor);
72     CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "Failed to set constructor");
73 
74     status = napi_define_properties(env, exports, sizeof(staticProperty) / sizeof(staticProperty[0]), staticProperty);
75     CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "Failed to define static function");
76 
77     MEDIA_LOGI("Js Init End");
78     return exports;
79 }
80 
Constructor(napi_env env,napi_callback_info info)81 napi_value ScreenCaptureMonitorNapi::Constructor(napi_env env, napi_callback_info info)
82 {
83     MediaTrace trace("ScreenCaptureMonitorNapi::Constructor");
84     MEDIA_LOGI("Js Constructor Start");
85     napi_value result = nullptr;
86     napi_get_undefined(env, &result);
87 
88     size_t argCount = 0;
89     napi_value jsThis = nullptr;
90     napi_status status = napi_get_cb_info(env, info, &argCount, nullptr, &jsThis, nullptr);
91     CHECK_AND_RETURN_RET_LOG(status == napi_ok, result, "failed to napi_get_cb_info");
92 
93     ScreenCaptureMonitorNapi *jsMonitor = new(std::nothrow) ScreenCaptureMonitorNapi();
94     CHECK_AND_RETURN_RET_LOG(jsMonitor != nullptr, result, "failed to new ScreenCaptureMonitorNapi");
95 
96     jsMonitor->env_ = env;
97 
98     sptr<ScreenCaptureMonitorCallback> monitorCb(new ScreenCaptureMonitorCallback(env));
99     jsMonitor->monitorCb_ = monitorCb;
100     CHECK_AND_RETURN_RET_LOG(jsMonitor->monitorCb_ != nullptr, result, "failed to CreateRecorderCb");
101     ScreenCaptureMonitor::GetInstance()->RegisterScreenCaptureMonitorListener(jsMonitor->monitorCb_);
102     status = napi_wrap(env, jsThis, reinterpret_cast<void *>(jsMonitor),
103                        ScreenCaptureMonitorNapi::Destructor, nullptr, nullptr);
104     if (status != napi_ok) {
105         delete jsMonitor;
106         MEDIA_LOGE("Failed to wrap native instance");
107         return result;
108     }
109 
110     MEDIA_LOGI("Js Constructor End");
111 
112     return jsThis;
113 }
114 
Destructor(napi_env env,void * nativeObject,void * finalize)115 void ScreenCaptureMonitorNapi::Destructor(napi_env env, void *nativeObject, void *finalize)
116 {
117     MediaTrace trace("ScreenCaptureMonitorNapi::Destructor");
118     MEDIA_LOGI("Js Destructor Start");
119     (void)finalize;
120     if (nativeObject != nullptr) {
121         ScreenCaptureMonitorNapi *napi = reinterpret_cast<ScreenCaptureMonitorNapi *>(nativeObject);
122         napi->monitorCb_ = nullptr;
123         delete napi;
124     }
125     MEDIA_LOGI("Js Destructor End");
126 }
127 
JsGetScreenCaptureMonitor(napi_env env,napi_callback_info info)128 napi_value ScreenCaptureMonitorNapi::JsGetScreenCaptureMonitor(napi_env env, napi_callback_info info)
129 {
130     MediaTrace trace("ScreenCaptureMonitorNapi::JsGetScreenCaptureMonitor");
131     MEDIA_LOGI("Js GetScreenCaptureMonitor Start");
132     napi_value result = nullptr;
133     napi_get_undefined(env, &result);
134 
135     // get args
136     napi_value jsThis = nullptr;
137     napi_value args[1] = { nullptr };
138     size_t argCount = 1;
139     napi_status status = napi_get_cb_info(env, info, &argCount, args, &jsThis, nullptr);
140     CHECK_AND_RETURN_RET_LOG(status == napi_ok, result, "failed to napi_get_cb_info");
141 
142     std::unique_ptr<ScreenCaptureMonitorAsyncContext> asyncCtx =
143         std::make_unique<ScreenCaptureMonitorAsyncContext>(env);
144     CHECK_AND_RETURN_RET_LOG(asyncCtx != nullptr, result, "failed to get AsyncContext");
145 
146     if (!SystemPermission()) {
147         SignError(asyncCtx.get(), MSERR_EXT_API9_PERMISSION_DENIED, "GetScreenCaptureMonitor", "system");
148     }
149 
150     asyncCtx->callbackRef = CommonNapi::CreateReference(env, args[0]);
151     asyncCtx->deferred = CommonNapi::CreatePromise(env, asyncCtx->callbackRef, result);
152     asyncCtx->JsResult = std::make_unique<MediaJsResultInstance>(constructor_);
153     asyncCtx->ctorFlag = true;
154 
155     auto ret = MediaAsyncContext::SendCompleteEvent(env, asyncCtx.get(), napi_eprio_immediate);
156     if (ret != napi_status::napi_ok) {
157         MEDIA_LOGE("failed to SendEvent, ret = %{public}d", ret);
158     }
159     asyncCtx.release();
160 
161     MEDIA_LOGI("Js JsGetScreenCaptureMonitor End");
162 
163     return result;
164 }
165 
JsSetEventCallback(napi_env env,napi_callback_info info)166 napi_value ScreenCaptureMonitorNapi::JsSetEventCallback(napi_env env, napi_callback_info info)
167 {
168     MediaTrace trace("ScreenCaptureMonitorNapi::JsSetEventCallback");
169     MEDIA_LOGI("JsSetEventCallback Start");
170     napi_value result = nullptr;
171     napi_get_undefined(env, &result);
172 
173     std::unique_ptr<ScreenCaptureMonitorAsyncContext> asyncCtx =
174         std::make_unique<ScreenCaptureMonitorAsyncContext>(env);
175     CHECK_AND_RETURN_RET_LOG(asyncCtx != nullptr, result, "failed to get AsyncContext");
176 
177     if (!SystemPermission()) {
178         SignError(asyncCtx.get(), MSERR_EXT_API9_PERMISSION_DENIED, "On", "system");
179     }
180 
181     size_t argCount = 2;
182     constexpr size_t requireArgc = 1;
183     napi_value args[2] = { nullptr, nullptr };
184     ScreenCaptureMonitorNapi *monitorNapi = ScreenCaptureMonitorNapi::GetJsInstanceAndArgs(env, info, argCount, args);
185     CHECK_AND_RETURN_RET_LOG(monitorNapi != nullptr, result, "Failed to retrieve instance");
186 
187     napi_valuetype valueType0 = napi_undefined;
188     napi_valuetype valueType1 = napi_undefined;
189 
190     if (argCount < requireArgc) {
191         return result;
192     }
193 
194     if (napi_typeof(env, args[0], &valueType0) != napi_ok || valueType0 != napi_string) {
195         return result;
196     }
197 
198     if (napi_typeof(env, args[1], &valueType1) != napi_ok || valueType1 != napi_function) {
199         return result;
200     }
201 
202     std::string callbackName = CommonNapi::GetStringArgument(env, args[0]);
203     if (callbackName != EVENT_SYSTEM_SCREEN_RECORD) {
204         return result;
205     }
206 
207     napi_ref ref = nullptr;
208     napi_status status = napi_create_reference(env, args[1], 1, &ref);
209     CHECK_AND_RETURN_RET_LOG(status == napi_ok && ref != nullptr, result, "failed to create reference!");
210 
211     std::shared_ptr<AutoRef> autoRef = std::make_shared<AutoRef>(env, ref);
212     monitorNapi->SetCallbackReference(callbackName, autoRef);
213 
214     MEDIA_LOGI("JsSetEventCallback End");
215     return result;
216 }
217 
JsCancelEventCallback(napi_env env,napi_callback_info info)218 napi_value ScreenCaptureMonitorNapi::JsCancelEventCallback(napi_env env, napi_callback_info info)
219 {
220     MediaTrace trace("ScreenCaptureMonitorNapi::JsCancelEventCallback");
221     MEDIA_LOGI("JsCancelEventCallback Start");
222     napi_value result = nullptr;
223     napi_get_undefined(env, &result);
224     constexpr size_t requireArgc = 1;
225     size_t argCount = 1;
226 
227     std::unique_ptr<ScreenCaptureMonitorAsyncContext> asyncCtx =
228         std::make_unique<ScreenCaptureMonitorAsyncContext>(env);
229     CHECK_AND_RETURN_RET_LOG(asyncCtx != nullptr, result, "failed to get AsyncContext");
230 
231     if (!SystemPermission()) {
232         SignError(asyncCtx.get(), MSERR_EXT_API9_PERMISSION_DENIED, "Off", "system");
233     }
234 
235     napi_value args[1] = { nullptr };
236     ScreenCaptureMonitorNapi *monitorNapi = ScreenCaptureMonitorNapi::GetJsInstanceAndArgs(env, info, argCount, args);
237     CHECK_AND_RETURN_RET_LOG(monitorNapi != nullptr, result, "Failed to retrieve instance");
238 
239     napi_valuetype valueType0 = napi_undefined;
240 
241     if (argCount < requireArgc) {
242         return result;
243     }
244 
245     if (napi_typeof(env, args[0], &valueType0) != napi_ok || valueType0 != napi_string) {
246         return result;
247     }
248 
249     std::string callbackName = CommonNapi::GetStringArgument(env, args[0]);
250     if (callbackName != EVENT_SYSTEM_SCREEN_RECORD) {
251         return result;
252     }
253 
254     monitorNapi->CancelCallbackReference(callbackName);
255 
256     MEDIA_LOGI("JsCancelEventCallback End");
257     return result;
258 }
259 
JsIsSystemScreenRecorderWorking(napi_env env,napi_callback_info info)260 napi_value ScreenCaptureMonitorNapi::JsIsSystemScreenRecorderWorking(napi_env env, napi_callback_info info)
261 {
262     MediaTrace trace("ScreenCaptureMonitorNapi::JsIsSystemScreenRecorderWorking");
263     MEDIA_LOGI("Js IsSystemScreenRecorderWorking Start");
264     napi_value result = nullptr;
265     napi_get_undefined(env, &result);
266 
267     std::unique_ptr<ScreenCaptureMonitorAsyncContext> asyncCtx =
268         std::make_unique<ScreenCaptureMonitorAsyncContext>(env);
269     CHECK_AND_RETURN_RET_LOG(asyncCtx != nullptr, result, "failed to get AsyncContext");
270 
271     if (!SystemPermission()) {
272         SignError(asyncCtx.get(), MSERR_EXT_API9_PERMISSION_DENIED, "IsSystemScreenRecorderWorking", "system");
273     }
274 
275     size_t argCount = 0;
276     bool isSystemScreenRecorderWorking = false;
277     napi_status status = napi_get_boolean(env, isSystemScreenRecorderWorking, &result);
278 
279     ScreenCaptureMonitorNapi *monitorNapi = ScreenCaptureMonitorNapi::GetJsInstanceAndArgs(
280         env, info, argCount, nullptr);
281     CHECK_AND_RETURN_RET_LOG(monitorNapi != nullptr, result, "Failed to GetJsInstanceAndArgs");
282 
283     isSystemScreenRecorderWorking = ScreenCaptureMonitor::GetInstance()->IsSystemScreenRecorderWorking();
284     status = napi_get_boolean(env, isSystemScreenRecorderWorking, &result);
285     CHECK_AND_RETURN_RET_LOG(status == napi_ok, result, "napi_get_boolean failed");
286 
287     return result;
288 }
289 
GetJsInstanceAndArgs(napi_env env,napi_callback_info info,size_t & argCount,napi_value * args)290 ScreenCaptureMonitorNapi *ScreenCaptureMonitorNapi::GetJsInstanceAndArgs(
291     napi_env env, napi_callback_info info, size_t &argCount, napi_value *args)
292 {
293     napi_value jsThis = nullptr;
294     napi_status status = napi_get_cb_info(env, info, &argCount, args, &jsThis, nullptr);
295     CHECK_AND_RETURN_RET_LOG(status == napi_ok && jsThis != nullptr, nullptr, "failed to napi_get_cb_info");
296     MEDIA_LOGD("argCount:%{public}zu", argCount);
297 
298     ScreenCaptureMonitorNapi *monitorNapi = nullptr;
299     status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&monitorNapi));
300     CHECK_AND_RETURN_RET_LOG(status == napi_ok && monitorNapi != nullptr, nullptr, "failed to retrieve instance");
301 
302     return monitorNapi;
303 }
304 
SetCallbackReference(const std::string & callbackName,std::shared_ptr<AutoRef> ref)305 void ScreenCaptureMonitorNapi::SetCallbackReference(const std::string &callbackName, std::shared_ptr<AutoRef> ref)
306 {
307     eventCbMap_[callbackName] = ref;
308     CHECK_AND_RETURN_LOG(monitorCb_ != nullptr, "monitorCb_ is nullptr!");
309     auto napiCb = static_cast<ScreenCaptureMonitorCallback*>(monitorCb_.GetRefPtr());
310     napiCb->SaveCallbackReference(callbackName, ref);
311 }
312 
CancelCallbackReference(const std::string & callbackName)313 void ScreenCaptureMonitorNapi::CancelCallbackReference(const std::string &callbackName)
314 {
315     CHECK_AND_RETURN_LOG(monitorCb_ != nullptr, "monitorCb_ is nullptr!");
316     auto napiCb = static_cast<ScreenCaptureMonitorCallback*>(monitorCb_.GetRefPtr());
317     napiCb->CancelCallbackReference(callbackName);
318     eventCbMap_[callbackName] = nullptr;
319 }
320 } // Media
321 } // OHOS