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