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