1 /*
2 * Copyright (c) 2023-2024 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_insight_intent_context.h"
17
18 #include "ability_window_configuration.h"
19 #include "hilog_tag_wrapper.h"
20 #include "hitrace_meter.h"
21 #include "js_error_utils.h"
22 #include "napi_common_want.h"
23
24 namespace OHOS {
25 namespace AbilityRuntime {
26 namespace {
27 constexpr static char CONTEXT_MODULE_NAME[] = "InsightIntentContext";
28 }
29
Finalizer(napi_env env,void * data,void * hint)30 void JsInsightIntentContext::Finalizer(napi_env env, void* data, void* hint)
31 {
32 TAG_LOGI(AAFwkTag::INTENT, "called");
33 std::unique_ptr<JsInsightIntentContext>(static_cast<JsInsightIntentContext*>(data));
34 }
35
StartAbiity(napi_env env,napi_callback_info info)36 napi_value JsInsightIntentContext::StartAbiity(napi_env env, napi_callback_info info)
37 {
38 HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
39 GET_NAPI_INFO_AND_CALL(env, info, JsInsightIntentContext, OnStartAbility);
40 }
41
OnStartAbility(napi_env env,NapiCallbackInfo & info)42 napi_value JsInsightIntentContext::OnStartAbility(napi_env env, NapiCallbackInfo& info)
43 {
44 TAG_LOGD(AAFwkTag::INTENT, "called");
45 HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
46
47 // unwrap want
48 AAFwk::Want want;
49
50 bool checkParamResult = CheckStartAbilityParam(env, info, want);
51 if (!checkParamResult) {
52 TAG_LOGE(AAFwkTag::INTENT, "check startAbility param failed");
53 return CreateJsUndefined(env);
54 }
55
56 auto context = context_.lock();
57 if (context == nullptr) {
58 TAG_LOGE(AAFwkTag::INTENT, "invalid context");
59 ThrowError(env, AbilityErrorCode::ERROR_CODE_INNER);
60 return CreateJsUndefined(env);
61 }
62
63 // verify if bundleName is empty or invalid
64 auto bundleNameFromWant = want.GetElement().GetBundleName();
65 if (bundleNameFromWant.empty() || bundleNameFromWant != context->GetBundleName()) {
66 TAG_LOGE(AAFwkTag::INTENT, "bundleName is empty or invalid");
67 ThrowError(env, AbilityErrorCode::ERROR_CODE_OPERATION_NOT_SUPPORTED);
68 return CreateJsUndefined(env);
69 }
70 // modify windowmode setting
71 auto windowMode = context->GetCurrentWindowMode();
72 if (windowMode == AAFwk::AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_PRIMARY ||
73 windowMode == AAFwk::AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_SECONDARY) {
74 want.SetParam(AAFwk::Want::PARAM_RESV_WINDOW_MODE, windowMode);
75 }
76
77 auto innerErrCode = std::make_shared<ErrCode>(ERR_OK);
78 // create execute task
79 NapiAsyncTask::ExecuteCallback execute = [weak = context_, want, innerErrCode]() {
80 auto context = weak.lock();
81 if (!context) {
82 TAG_LOGE(AAFwkTag::INTENT, "context is released");
83 *innerErrCode = static_cast<int>(AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT);
84 return;
85 }
86 *innerErrCode = context->StartAbilityByInsightIntent(want);
87 };
88 // create complete task
89 NapiAsyncTask::CompleteCallback complete = [innerErrCode](napi_env env, NapiAsyncTask& task, int32_t status) {
90 if (*innerErrCode == ERR_OK) {
91 task.Resolve(env, CreateJsUndefined(env));
92 } else {
93 task.Reject(env, CreateJsErrorByNativeErr(env, *innerErrCode));
94 }
95 };
96
97 napi_value lastParam = (info.argc > 1) ? info.argv[1] : nullptr;
98 napi_value result = nullptr;
99 NapiAsyncTask::ScheduleHighQos("JsInsightIntentContext::OnStartAbility", env,
100 CreateAsyncTaskWithLastParam(env, lastParam, std::move(execute), std::move(complete), &result));
101 TAG_LOGD(AAFwkTag::INTENT, "end");
102 return result;
103 }
104
CreateJsInsightIntentContext(napi_env env,const std::shared_ptr<InsightIntentContext> & context)105 napi_value CreateJsInsightIntentContext(napi_env env, const std::shared_ptr<InsightIntentContext>& context)
106 {
107 TAG_LOGD(AAFwkTag::INTENT, "called");
108 napi_value contextObj;
109 napi_create_object(env, &contextObj);
110
111 std::unique_ptr<JsInsightIntentContext> jsInsightIntentContext = std::make_unique<JsInsightIntentContext>(context);
112 napi_wrap(env, contextObj, jsInsightIntentContext.release(), JsInsightIntentContext::Finalizer, nullptr, nullptr);
113
114 BindNativeFunction(env, contextObj, "startAbility", CONTEXT_MODULE_NAME, JsInsightIntentContext::StartAbiity);
115 TAG_LOGD(AAFwkTag::INTENT, "end");
116 return contextObj;
117 }
118
CheckStartAbilityParam(napi_env env,NapiCallbackInfo & info,AAFwk::Want & want)119 bool CheckStartAbilityParam(napi_env env, NapiCallbackInfo& info, AAFwk::Want& want)
120 {
121 if (info.argc == 0) {
122 TAG_LOGE(AAFwkTag::INTENT, "invalid argc");
123 ThrowTooFewParametersError(env);
124 return false;
125 }
126
127 // unwrap want
128 bool unwrapWantFlag = OHOS::AppExecFwk::UnwrapWant(env, info.argv[0], want);
129 if (!unwrapWantFlag) {
130 TAG_LOGE(AAFwkTag::INTENT, "parse want fail");
131 ThrowInvalidParamError(env, "Parameter error: Failed to parse want, must be a Want.");
132 return false;
133 }
134 return true;
135 }
136 } // namespace AbilityRuntime
137 } // namespace OHOS
138