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_context.h"
17
18 #include <js_runtime_utils.h>
19 #include <js_extension_context.h>
20
21 #include "napi_common_start_options.h"
22 #include "napi_common_want.h"
23 #include "service_extension_context.h"
24 #include "start_options.h"
25 #include "window_manager_hilog.h"
26
27 namespace OHOS {
28 namespace Rosen {
29 using namespace AbilityRuntime;
30
31 namespace {
32 constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "JSWindowExtensionContext"};
33 std::shared_ptr<AppExecFwk::EventHandler> handler_;
34 }
35
36 class JsWindowExtensionContext final {
37 public:
JsWindowExtensionContext(const std::shared_ptr<WindowExtensionContext> & context)38 explicit JsWindowExtensionContext(
39 const std::shared_ptr<WindowExtensionContext>& context) : context_(context) {}
40 ~JsWindowExtensionContext() = default;
41
Finalizer(NativeEngine * engine,void * data,void * hint)42 static void Finalizer(NativeEngine* engine, void* data, void* hint)
43 {
44 WLOGI("JsWindowExtensionContext::Finalizer is called");
45 std::unique_ptr<JsWindowExtensionContext>(static_cast<JsWindowExtensionContext*>(data));
46 }
47
StartAbility(NativeEngine * engine,NativeCallbackInfo * info)48 static NativeValue* StartAbility(NativeEngine* engine, NativeCallbackInfo* info)
49 {
50 JsWindowExtensionContext* me = CheckParamsAndGetThis<JsWindowExtensionContext>(engine, info);
51 return (me != nullptr) ? me->OnStartAbility(*engine, *info) : nullptr;
52 }
53 private:
54 std::weak_ptr<WindowExtensionContext> context_;
55
CheckStartAbilityInputParam(NativeEngine & engine,NativeCallbackInfo & info,AAFwk::Want & want,AAFwk::StartOptions & startOptions) const56 bool CheckStartAbilityInputParam(
57 NativeEngine& engine, NativeCallbackInfo& info,
58 AAFwk::Want& want, AAFwk::StartOptions& startOptions) const
59 {
60 if (info.argc < 1) {
61 return false;
62 }
63 // Check input want
64 if (!CheckWantParam(engine, info.argv[0], want)) {
65 return false;
66 }
67 if (info.argc > 1 && info.argv[1]->TypeOf() == NATIVE_OBJECT) {
68 WLOGI("OnStartAbility start options is used.");
69 AppExecFwk::UnwrapStartOptions(reinterpret_cast<napi_env>(&engine),
70 reinterpret_cast<napi_value>(info.argv[1]), startOptions);
71 }
72 return true;
73 }
74
CheckWantParam(NativeEngine & engine,NativeValue * value,AAFwk::Want & want) const75 bool CheckWantParam(NativeEngine& engine, NativeValue* value, AAFwk::Want& want) const
76 {
77 if (!OHOS::AppExecFwk::UnwrapWant(reinterpret_cast<napi_env>(&engine),
78 reinterpret_cast<napi_value>(value), want)) {
79 WLOGFE("The input want is invalid.");
80 return false;
81 }
82 WLOGI("UnwrapWant, BundleName: %{public}s, AbilityName: %{public}s.",
83 want.GetBundle().c_str(),
84 want.GetElement().GetAbilityName().c_str());
85 return true;
86 }
87
OnStartAbility(NativeEngine & engine,NativeCallbackInfo & info)88 NativeValue* OnStartAbility(NativeEngine& engine, NativeCallbackInfo& info)
89 {
90 WLOGI("OnStartAbility is called");
91 if (info.argc < 2) { // at least two argc
92 WLOGFE("Start ability failed, not enough params.");
93 engine.Throw(CreateJsError(engine, static_cast<int32_t>(WmErrorCode::WM_ERROR_INVALID_PARAM)));
94 return engine.CreateUndefined();
95 }
96
97 AAFwk::Want want;
98 AAFwk::StartOptions startOptions;
99 if (!CheckStartAbilityInputParam(engine, info, want, startOptions)) {
100 engine.Throw(CreateJsError(engine, static_cast<int32_t>(WmErrorCode::WM_ERROR_INVALID_PARAM)));
101 return engine.CreateUndefined();
102 }
103
104 AsyncTask::CompleteCallback complete =
105 [weak = context_, want, startOptions](NativeEngine& engine, AsyncTask& task, int32_t status) {
106 WLOGI("startAbility begin");
107 auto context = weak.lock();
108 if (!context) {
109 WLOGFW("context is released");
110 task.Reject(engine, CreateJsError(engine,
111 static_cast<int32_t>(WmErrorCode::WM_ERROR_STATE_ABNORMALLY)));
112 return;
113 }
114
115 WmErrorCode ret = WM_JS_TO_ERROR_CODE_MAP.at(context->StartAbility(want, startOptions));
116 if (ret == WmErrorCode::WM_OK) {
117 task.Resolve(engine, engine.CreateUndefined());
118 } else {
119 task.Reject(engine, CreateJsError(engine, static_cast<int32_t>(ret)));
120 }
121 };
122
123 NativeValue* lastParam = (info.argc <= 2) ? nullptr : info.argv[2]; // at least two argc
124 NativeValue* result = nullptr;
125 AsyncTask::Schedule("JSServiceExtensionContext::OnStartAbility",
126 engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result));
127 return result;
128 }
129 };
130
OnAbilityConnectDone(const AppExecFwk::ElementName & element,const sptr<IRemoteObject> & remoteObject,int resultCode)131 void JsWindowConnectCallback::OnAbilityConnectDone(const AppExecFwk::ElementName& element,
132 const sptr<IRemoteObject>& remoteObject, int resultCode)
133 {
134 WLOGI("called");
135 }
136
OnAbilityDisconnectDone(const AppExecFwk::ElementName & element,int resultCode)137 void JsWindowConnectCallback::OnAbilityDisconnectDone(const AppExecFwk::ElementName& element, int resultCode)
138 {
139 WLOGI("called");
140 }
141
CreateJsWindowExtensionContext(NativeEngine & engine,const std::shared_ptr<WindowExtensionContext> & context)142 NativeValue* CreateJsWindowExtensionContext(NativeEngine& engine,
143 const std::shared_ptr<WindowExtensionContext>& context)
144 {
145 WLOGI("CreateJsWindowExtensionContext begin");
146 NativeValue* objValue = CreateJsExtensionContext(engine, context);
147 NativeObject* object = AbilityRuntime::ConvertNativeValueTo<NativeObject>(objValue);
148
149 std::unique_ptr<JsWindowExtensionContext> jsContext
150 = std::make_unique<JsWindowExtensionContext>(context);
151 object->SetNativePointer(jsContext.release(), JsWindowExtensionContext::Finalizer, nullptr);
152
153 // make handler
154 handler_ = std::make_shared<AppExecFwk::EventHandler>(AppExecFwk::EventRunner::GetMainEventRunner());
155
156 const char *moduleName = "JsWindowExtensionContext";
157 BindNativeFunction(engine, *object, "startAbility", moduleName, JsWindowExtensionContext::StartAbility);
158
159 return objValue;
160 }
161 } // namespace Rosen
162 } // namespace OHOS