• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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_window_extension.h"
17 
18 #include <hitrace_meter.h>
19 #include <napi_common_want.h>
20 #include <native_engine/native_reference.h>
21 #include <native_engine/native_value.h>
22 #include <js_extension_context.h>
23 #include <js_runtime_utils.h>
24 
25 #include "js_window.h"
26 #include "js_window_extension_context.h"
27 #include "window_extension_connection.h"
28 #include "window_manager_hilog.h"
29 #include "wm_common.h"
30 #include "wm_common_inner.h"
31 
32 namespace OHOS {
33 namespace Rosen {
34 namespace {
35     constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "JSWindowExtension"};
36 }
37 
38 class DispatchInputEventListener : public IDispatchInputEventListener {
39 public:
OnDispatchPointerEvent(std::shared_ptr<MMI::PointerEvent> & inputEvent)40     void OnDispatchPointerEvent(std::shared_ptr<MMI::PointerEvent>& inputEvent) override
41     {
42         WLOGFI("called");
43     }
OnDispatchKeyEvent(std::shared_ptr<MMI::KeyEvent> & keyEvent)44     void OnDispatchKeyEvent(std::shared_ptr<MMI::KeyEvent>& keyEvent) override
45     {
46         WLOGFI("called");
47     }
48 };
49 
AttachWindowExtensionContext(NativeEngine * engine,void * value,void *)50 NativeValue *AttachWindowExtensionContext(NativeEngine *engine, void *value, void *)
51 {
52     WLOGFI("AttachWindowExtensionContext");
53     if (value == nullptr) {
54         WLOGFE("invalid parameter.");
55         return nullptr;
56     }
57     auto ptr = reinterpret_cast<std::weak_ptr<WindowExtensionContext> *>(value)->lock();
58     if (ptr == nullptr) {
59         WLOGFE("invalid context.");
60         return nullptr;
61     }
62     NativeValue* object = CreateJsWindowExtensionContext(*engine, ptr);
63     if (object == nullptr) {
64         WLOGFE("Failed to get js window extension context");
65         return nullptr;
66     }
67     auto contextObj = AbilityRuntime::JsRuntime::LoadSystemModuleByEngine(engine,
68         "application.WindowExtensionContext", &object, 1)->Get();
69     NativeObject* nObject = AbilityRuntime::ConvertNativeValueTo<NativeObject>(contextObj);
70     if (nObject == nullptr) {
71         WLOGFE("Failed to get context native object");
72         return nullptr;
73     }
74     nObject->ConvertToNativeBindingObject(engine, AbilityRuntime::DetachCallbackFunc, AttachWindowExtensionContext,
75         value, nullptr);
76     auto workContext = new (std::nothrow) std::weak_ptr<WindowExtensionContext>(ptr);
77     if (workContext == nullptr) {
78         WLOGFE("Failed to get window extension context");
79         return nullptr;
80     }
81     nObject->SetNativePointer(workContext,
82         [](NativeEngine *, void *data, void *) {
83             WLOGFI("Finalizer for weak_ptr service extension context is called");
84             delete static_cast<std::weak_ptr<WindowExtensionContext> *>(data);
85         }, nullptr);
86     return contextObj;
87 }
88 
Create(const std::unique_ptr<AbilityRuntime::Runtime> & runtime)89 JsWindowExtension* JsWindowExtension::Create(const std::unique_ptr<AbilityRuntime::Runtime>& runtime)
90 {
91     WLOGFD("Create runtime");
92     return new JsWindowExtension(static_cast<AbilityRuntime::JsRuntime&>(*runtime));
93 }
94 
JsWindowExtension(AbilityRuntime::JsRuntime & jsRuntime)95 JsWindowExtension::JsWindowExtension(AbilityRuntime::JsRuntime& jsRuntime) : jsRuntime_(jsRuntime) {}
96 JsWindowExtension::~JsWindowExtension() = default;
97 
Init(const std::shared_ptr<AbilityRuntime::AbilityLocalRecord> & record,const std::shared_ptr<AbilityRuntime::OHOSApplication> & application,std::shared_ptr<AbilityRuntime::AbilityHandler> & handler,const sptr<IRemoteObject> & token)98 void JsWindowExtension::Init(const std::shared_ptr<AbilityRuntime::AbilityLocalRecord>& record,
99     const std::shared_ptr<AbilityRuntime::OHOSApplication>& application,
100     std::shared_ptr<AbilityRuntime::AbilityHandler>& handler,
101     const sptr<IRemoteObject>& token)
102 {
103     HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "WindowExtension Init");
104     WindowExtension::Init(record, application, handler, token);
105     std::string srcPath;
106     GetSrcPath(srcPath);
107     if (srcPath.empty()) {
108         WLOGFE("Failed to get srcPath");
109         return;
110     }
111 
112     std::string moduleName(Extension::abilityInfo_->moduleName);
113     moduleName.append("::").append(abilityInfo_->name);
114     WLOGFI("JsWindowExtension::Init module:%{public}s,srcPath:%{public}s.", moduleName.c_str(), srcPath.c_str());
115     AbilityRuntime::HandleScope handleScope(jsRuntime_);
116 
117     jsObj_ = jsRuntime_.LoadModule(moduleName, srcPath, abilityInfo_->hapPath);
118     if (jsObj_ == nullptr) {
119         WLOGFE("Failed to get jsObj_");
120         return;
121     }
122     WLOGFI("JsWindowExtension::Init ConvertNativeValueTo.");
123     auto& engine = jsRuntime_.GetNativeEngine();
124     NativeObject* obj = AbilityRuntime::ConvertNativeValueTo<NativeObject>(jsObj_->Get());
125     if (obj == nullptr) {
126         WLOGFE("Failed to get JsWindowExtension object");
127         return;
128     }
129 
130     BindContext(engine, obj);
131 }
132 
BindContext(NativeEngine & engine,NativeObject * obj)133 void JsWindowExtension::BindContext(NativeEngine& engine, NativeObject* obj)
134 {
135     auto context = GetContext();
136     if (context == nullptr) {
137         WLOGFE("Failed to get context");
138         return;
139     }
140 
141     NativeValue* contextObj = CreateJsWindowExtensionContext(jsRuntime_.GetNativeEngine(), context);
142     if (contextObj == nullptr) {
143         WLOGFE("Failed to get js window extension context");
144         return;
145     }
146     shellContextRef_ = jsRuntime_.LoadSystemModule("application.WindowExtensionContext", &contextObj, 1);
147     contextObj = shellContextRef_->Get();
148     NativeObject* nativeObj = AbilityRuntime::ConvertNativeValueTo<NativeObject>(contextObj);
149     if (nativeObj == nullptr) {
150         WLOGFE("Failed to get context native object");
151         return;
152     }
153     auto workContext = new (std::nothrow) std::weak_ptr<WindowExtensionContext>(context);
154     if (workContext == nullptr) {
155         WLOGFE("Failed to get window extension context");
156         return;
157     }
158     nativeObj->ConvertToNativeBindingObject(&engine, AbilityRuntime::DetachCallbackFunc, AttachWindowExtensionContext,
159         workContext, nullptr);
160     WLOGFI("JsWindowExtension::Init Bind.");
161     context->Bind(jsRuntime_, shellContextRef_.get());
162     WLOGFI("JsWindowExtension::SetProperty.");
163     obj->SetProperty("context", contextObj);
164 
165     nativeObj->SetNativePointer(workContext,
166         [](NativeEngine *, void *data, void *) {
167             WLOGFI("Finalizer for weak_ptr extension context is called");
168             delete static_cast<std::weak_ptr<WindowExtensionContext>*>(data);
169         }, nullptr);
170 
171     WLOGFI("JsWindowExtension::Init end.");
172 }
173 
GetSrcPath(std::string & srcPath) const174 void JsWindowExtension::GetSrcPath(std::string& srcPath) const
175 {
176     if (!Extension::abilityInfo_) {
177         WLOGFE("abilityInfo_ is nullptr");
178         return;
179     }
180 
181     if (!Extension::abilityInfo_->isModuleJson) {
182         srcPath.append(Extension::abilityInfo_->package);
183         srcPath.append("/assets/js/");
184         if (!Extension::abilityInfo_->srcPath.empty()) {
185             srcPath.append(Extension::abilityInfo_->srcPath);
186         }
187         srcPath.append("/").append(Extension::abilityInfo_->name).append(".abc");
188         return;
189     }
190 
191     if (!Extension::abilityInfo_->srcEntrance.empty()) {
192         srcPath.append(Extension::abilityInfo_->moduleName + "/");
193         srcPath.append(Extension::abilityInfo_->srcEntrance);
194         srcPath.erase(srcPath.rfind('.'));
195         srcPath.append(".abc");
196     }
197 }
198 
OnConnect(const AAFwk::Want & want)199 sptr<IRemoteObject> JsWindowExtension::OnConnect(const AAFwk::Want& want)
200 {
201     HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "WindowExtension OnConnect %s-%s",
202         want.GetElement().GetAbilityName().c_str(), want.GetElement().GetAbilityName().c_str());
203     WLOGFI("called.");
204     Extension::OnConnect(want);
205     NativeEngine& engine = jsRuntime_.GetNativeEngine();
206     std::unique_ptr<AbilityRuntime::AsyncTask::CompleteCallback> complete =
207         std::make_unique<AbilityRuntime::AsyncTask::CompleteCallback>(
208         [=] (NativeEngine& engine, AbilityRuntime::AsyncTask& task, int32_t status) {
209             NativeEngine* nativeEngine = &jsRuntime_.GetNativeEngine();
210             napi_value napiWant = OHOS::AppExecFwk::WrapWant(reinterpret_cast<napi_env>(nativeEngine), want);
211             NativeValue* nativeWant = reinterpret_cast<NativeValue*>(napiWant);
212             NativeValue* argv[] = { nativeWant };
213             CallJsMethod("onConnect", argv, AbilityRuntime::ArraySize(argv));
214         }
215     );
216     NativeReference* callback = nullptr;
217     std::unique_ptr<AbilityRuntime::AsyncTask::ExecuteCallback> execute = nullptr;
218     AbilityRuntime::AsyncTask::Schedule("JsWindowExtension::OnConnect", engine,
219         std::make_unique<AbilityRuntime::AsyncTask>(callback, std::move(execute), std::move(complete)));
220 
221     if (!stub_) {
222         WLOGFE("stub is nullptr.");
223         return nullptr;
224     }
225     WLOGFD("Create stub successfully!");
226     return stub_->AsObject();
227 }
228 
OnDisconnect(const AAFwk::Want & want)229 void JsWindowExtension::OnDisconnect(const AAFwk::Want& want)
230 {
231     Extension::OnDisconnect(want);
232     NativeEngine& engine = jsRuntime_.GetNativeEngine();
233     std::unique_ptr<AbilityRuntime::AsyncTask::CompleteCallback> complete =
234         std::make_unique<AbilityRuntime::AsyncTask::CompleteCallback>(
235         [=] (NativeEngine& engine, AbilityRuntime::AsyncTask& task, int32_t status) {
236             NativeEngine* nativeEngine = &jsRuntime_.GetNativeEngine();
237             napi_value napiWant = OHOS::AppExecFwk::WrapWant(reinterpret_cast<napi_env>(nativeEngine), want);
238             NativeValue* nativeWant = reinterpret_cast<NativeValue*>(napiWant);
239             NativeValue* argv[] = { nativeWant };
240             CallJsMethod("onDisconnect", argv, AbilityRuntime::ArraySize(argv));
241         }
242     );
243     NativeReference* callback = nullptr;
244     std::unique_ptr<AbilityRuntime::AsyncTask::ExecuteCallback> execute = nullptr;
245     AbilityRuntime::AsyncTask::Schedule("JsWindowExtension::OnDisconnect", engine,
246         std::make_unique<AbilityRuntime::AsyncTask>(callback, std::move(execute), std::move(complete)));
247 
248     auto window = stub_ != nullptr ? stub_->GetWindow() : nullptr;
249     if (window != nullptr) {
250         window->Destroy();
251         WLOGFI("Destroy window.");
252     }
253     WLOGFI("called.");
254 }
255 
OnStart(const AAFwk::Want & want)256 void JsWindowExtension::OnStart(const AAFwk::Want& want)
257 {
258     HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "WindowExtension OnStart %s-%s",
259         want.GetElement().GetAbilityName().c_str(), want.GetElement().GetAbilityName().c_str());
260     Extension::OnStart(want);
261 
262     AbilityRuntime::ElementName elementName = want.GetElement();
263     std::string windowName = elementName.GetBundleName();
264 
265     stub_ = new(std::nothrow) WindowExtensionStubImpl(windowName);
266     WLOGFI("JsWindowExtension OnStart begin..");
267     Rect rect { want.GetIntParam(RECT_FORM_KEY_POS_X, 0),
268     want.GetIntParam(RECT_FORM_KEY_POS_Y, 0),
269     want.GetIntParam(RECT_FORM_KEY_WIDTH, 0),
270     want.GetIntParam(RECT_FORM_KEY_HEIGHT, 0) };
271     uint32_t windowId = static_cast<uint32_t>(want.GetIntParam(WINDOW_ID, INVALID_WINDOW_ID));
272     if (stub_ != nullptr) {
273         auto context = GetContext();
274         if (context == nullptr) {
275             WLOGFE("get context failed");
276             return;
277         }
278         sptr<Window> window = stub_->CreateWindow(rect, windowId, context);
279         if (window == nullptr) {
280             WLOGFE("create window failed");
281             return;
282         }
283         OnWindowCreated();
284         WLOGFI("ability context onWindowReady rect x =%{public}d y=%{public}d w=%{public}d h=%{public}d ",
285             rect.posX_, rect.posY_, rect.width_, rect.height_);
286     }
287 }
288 
OnWindowCreated() const289 void JsWindowExtension::OnWindowCreated() const
290 {
291     NativeEngine& engine = jsRuntime_.GetNativeEngine();
292     std::unique_ptr<AbilityRuntime::AsyncTask::CompleteCallback> complete =
293         std::make_unique<AbilityRuntime::AsyncTask::CompleteCallback>(
294         [=] (NativeEngine& engine, AbilityRuntime::AsyncTask& task, int32_t status) {
295             auto window = stub_->GetWindow();
296             if (window == nullptr) {
297                 WLOGFE("get window failed");
298                 return;
299             }
300             NativeValue* value = CreateJsWindowObject(engine, window);
301             if (value == nullptr) {
302                 WLOGFE("Create js window failed");
303                 return;
304             }
305             NativeValue* argv[] = { value };
306             CallJsMethod("onWindowReady", argv, AbilityRuntime::ArraySize(argv));
307         }
308     );
309 
310     NativeReference* callback = nullptr;
311     std::unique_ptr<AbilityRuntime::AsyncTask::ExecuteCallback> execute = nullptr;
312     AbilityRuntime::AsyncTask::Schedule("JsWindowExtension::OnWindowCreated", engine,
313         std::make_unique<AbilityRuntime::AsyncTask>(callback, std::move(execute), std::move(complete)));
314 }
315 
CallJsMethod(const char * name,NativeValue * const * argv,size_t argc) const316 NativeValue* JsWindowExtension::CallJsMethod(const char* name, NativeValue* const* argv, size_t argc) const
317 {
318     WLOGFI("called (%{public}s), begin", name);
319 
320     if (!jsObj_) {
321         WLOGFW("Not found WindowExtension.js");
322         return nullptr;
323     }
324 
325     AbilityRuntime::HandleScope handleScope(jsRuntime_);
326     auto& nativeEngine = jsRuntime_.GetNativeEngine();
327 
328     NativeValue* value = jsObj_->Get();
329     NativeObject* obj = AbilityRuntime::ConvertNativeValueTo<NativeObject>(value);
330     if (obj == nullptr) {
331         WLOGFE("Failed to get WindowExtension object");
332         return nullptr;
333     }
334 
335     NativeValue* method = obj->GetProperty(name);
336     if (method == nullptr || method->TypeOf() != NATIVE_FUNCTION) {
337         WLOGFE("Failed to get '%{public}s' from WindowExtension object", name);
338         return nullptr;
339     }
340     WLOGFI("(%{public}s), success", name);
341     return nativeEngine.CallFunction(value, method, argv, argc);
342 }
343 } // namespace Rosen
344 } // namespace OHOS
345