• 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 
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