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