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 "ashmem.h"
17 #include <gtest/gtest.h>
18 #include "json_utils.h"
19 #include <sys/mman.h>
20
21 #include "account_log_wrapper.h"
22 #define private public
23 #include "bundle_manager_adapter.h"
24 #include "bundle_manager_adapter_proxy.h"
25 #undef private
26 #include "iservice_registry.h"
27 #include "system_ability_definition.h"
28 #include "system_ability.h"
29
30 using namespace testing::ext;
31 using namespace OHOS;
32 using namespace OHOS::AccountSA;
33
34 class BundleManagerModuleTest : public testing::Test {
35 public:
36 static void SetUpTestCase(void);
37 static void TearDownTestCase(void);
38 void SetUp(void) override;
39 void TearDown(void) override;
40
41 std::shared_ptr<BundleManagerAdapterProxy> g_bundleManagerAdapterProxyRemoteNull =
42 std::make_shared<BundleManagerAdapterProxy>(nullptr);
43 };
44
45 namespace {
46 const std::string EMPTY_BUNDLE_NAME = "";
47 const std::string INVALID_BUNDLE_NAME = "testbundlename";
48 const std::string BUNDLE_NAME = "com.ohos.launcher";
49 const int32_t FLAGS = 1;
50 const int32_t USER_ID = 1;
51 } // namespace
52
SetUpTestCase(void)53 void BundleManagerModuleTest::SetUpTestCase(void)
54 {}
55
TearDownTestCase(void)56 void BundleManagerModuleTest::TearDownTestCase(void)
57 {}
58
SetUp(void)59 void BundleManagerModuleTest::SetUp(void) __attribute__((no_sanitize("cfi")))
60 {
61 testing::UnitTest *test = testing::UnitTest::GetInstance();
62 ASSERT_NE(test, nullptr);
63 const testing::TestInfo *testinfo = test->current_test_info();
64 ASSERT_NE(testinfo, nullptr);
65 string testCaseName = string(testinfo->name());
66 ACCOUNT_LOGI("[SetUp] %{public}s start", testCaseName.c_str());
67 }
68
TearDown(void)69 void BundleManagerModuleTest::TearDown(void)
70 {}
71
72 /**
73 * @tc.name: BundleManagerProxy_GetBundleInfo_0100
74 * @tc.desc: test func failed with remote is null
75 * @tc.type: FUNC
76 * @tc.require:
77 */
78 HWTEST_F(BundleManagerModuleTest, BundleManagerProxy_GetBundleInfo_0100, TestSize.Level1)
79 {
80 ASSERT_NE(g_bundleManagerAdapterProxyRemoteNull, nullptr);
81 BundleInfo bundleInfo;
82 bool result = g_bundleManagerAdapterProxyRemoteNull->GetBundleInfo(
83 INVALID_BUNDLE_NAME, BundleFlag::GET_BUNDLE_WITH_ABILITIES, bundleInfo, USER_ID);
84 ASSERT_EQ(result, false);
85
86 Want want;
87 std::vector<AbilityInfo> abilityInfos;
88 result = g_bundleManagerAdapterProxyRemoteNull->QueryAbilityInfos(want, FLAGS, USER_ID, abilityInfos);
89 ASSERT_EQ(result, false);
90
91 std::vector<ExtensionAbilityInfo> extensionInfos;
92 result = g_bundleManagerAdapterProxyRemoteNull->QueryExtensionAbilityInfos(want, FLAGS, USER_ID, extensionInfos);
93 ASSERT_EQ(result, false);
94 }
95
96 /**
97 * @tc.name: BundleManagerProxy_GetBundleInfo_0200
98 * @tc.desc: test GetBundleInfo param is invalid
99 * @tc.type: FUNC
100 * @tc.require:
101 */
102 HWTEST_F(BundleManagerModuleTest, BundleManagerProxy_GetBundleInfo_0200, TestSize.Level1)
103 {
104 sptr<ISystemAbilityManager> systemAbilityManager =
105 SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
106 ASSERT_NE(systemAbilityManager, nullptr);
107 sptr<IRemoteObject> remoteObj = systemAbilityManager->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
108 ASSERT_NE(remoteObj, nullptr);
109 auto bundleManagerAdapterProxy = std::make_shared<BundleManagerAdapterProxy>(remoteObj);
110 ASSERT_NE(bundleManagerAdapterProxy, nullptr);
111
112 BundleInfo bundleInfo;
113 bool result = bundleManagerAdapterProxy->GetBundleInfo(
114 INVALID_BUNDLE_NAME, BundleFlag::GET_BUNDLE_WITH_ABILITIES, bundleInfo, USER_ID);
115 ASSERT_EQ(result, false);
116 }
117
118 /**
119 * @tc.name: BundleManagerProxy_GetBundleInfo_0300
120 * @tc.desc: test GetBundleInfo param is invalid
121 * @tc.type: FUNC
122 * @tc.require:
123 */
124 HWTEST_F(BundleManagerModuleTest, BundleManagerProxy_GetBundleInfo_0300, TestSize.Level1)
125 {
126 sptr<ISystemAbilityManager> systemAbilityManager =
127 SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
128 ASSERT_NE(systemAbilityManager, nullptr);
129 sptr<IRemoteObject> remoteObj = systemAbilityManager->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
130 ASSERT_NE(remoteObj, nullptr);
131 auto bundleManagerAdapterProxy = std::make_shared<BundleManagerAdapterProxy>(remoteObj);
132 ASSERT_NE(bundleManagerAdapterProxy, nullptr);
133
134 BundleInfo bundleInfo;
135 bool result = bundleManagerAdapterProxy->GetBundleInfo(
136 EMPTY_BUNDLE_NAME, BundleFlag::GET_BUNDLE_WITH_ABILITIES, bundleInfo, USER_ID);
137 ASSERT_EQ(result, false);
138 }
139
140 /**
141 * @tc.name: BundleManagerProxy_GetUidByBundleName_0100
142 * @tc.desc: test GetUidByBundleName failed with bundlename is empty
143 * @tc.type: FUNC
144 * @tc.require:
145 */
146 HWTEST_F(BundleManagerModuleTest, BundleManagerProxy_GetUidByBundleName_0100, TestSize.Level1)
147 {
148 sptr<ISystemAbilityManager> systemAbilityManager =
149 SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
150 ASSERT_NE(systemAbilityManager, nullptr);
151 sptr<IRemoteObject> remoteObj = systemAbilityManager->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
152 ASSERT_NE(remoteObj, nullptr);
153 auto bundleManagerAdapterProxy = std::make_shared<BundleManagerAdapterProxy>(remoteObj);
154 ASSERT_NE(bundleManagerAdapterProxy, nullptr);
155
156 int32_t result = bundleManagerAdapterProxy->GetUidByBundleName(EMPTY_BUNDLE_NAME, USER_ID);
157 ASSERT_EQ(result, AppExecFwk::Constants::INVALID_UID);
158 }
159
160 /**
161 * @tc.name: BundleManagerProxy_QueryAbilityInfos_0200
162 * @tc.desc: test QueryAbilityInfos failed with param is invalid
163 * @tc.type: FUNC
164 * @tc.require:
165 */
166 HWTEST_F(BundleManagerModuleTest, BundleManagerProxy_QueryAbilityInfos_0200, TestSize.Level1)
167 {
168 sptr<ISystemAbilityManager> systemAbilityManager =
169 SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
170 ASSERT_NE(systemAbilityManager, nullptr);
171 sptr<IRemoteObject> remoteObj = systemAbilityManager->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
172 ASSERT_NE(remoteObj, nullptr);
173 auto bundleManagerAdapterProxy = std::make_shared<BundleManagerAdapterProxy>(remoteObj);
174 ASSERT_NE(bundleManagerAdapterProxy, nullptr);
175
176 Want want;
177 std::vector<AbilityInfo> abilityInfos;
178 bool result = bundleManagerAdapterProxy->QueryAbilityInfos(want, FLAGS, USER_ID, abilityInfos);
179 ASSERT_EQ(result, false);
180 }
181
182 /**
183 * @tc.name: BundleManagerProxy_QueryExtensionAbilityInfos_0200
184 * @tc.desc: test QueryExtensionAbilityInfos failed with param is invalid
185 * @tc.type: FUNC
186 * @tc.require:
187 */
188 HWTEST_F(BundleManagerModuleTest, BundleManagerProxy_QueryExtensionAbilityInfos_0200, TestSize.Level1)
189 {
190 sptr<ISystemAbilityManager> systemAbilityManager =
191 SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
192 ASSERT_NE(systemAbilityManager, nullptr);
193 sptr<IRemoteObject> remoteObj = systemAbilityManager->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
194 ASSERT_NE(remoteObj, nullptr);
195 auto bundleManagerAdapterProxy = std::make_shared<BundleManagerAdapterProxy>(remoteObj);
196 ASSERT_NE(bundleManagerAdapterProxy, nullptr);
197
198 Want want;
199 std::vector<ExtensionAbilityInfo> extensionInfos;
200 bool result = bundleManagerAdapterProxy->QueryExtensionAbilityInfos(want, FLAGS, USER_ID, extensionInfos);
201 ASSERT_EQ(result, false);
202 }
203
204 /**
205 * @tc.name: BundleManagerAdapter_GetBundleInfo_0100
206 * @tc.desc: test GetBundleInfo failed with param is invalid
207 * @tc.type: FUNC
208 * @tc.require:
209 */
210 HWTEST_F(BundleManagerModuleTest, BundleManagerAdapter_GetBundleInfo_0100, TestSize.Level1)
211 {
212 BundleInfo bundleInfo;
213 bool result = BundleManagerAdapter::GetInstance()->GetBundleInfo(
214 BUNDLE_NAME, BundleFlag::GET_BUNDLE_WITH_ABILITIES, bundleInfo, USER_ID);
215 ASSERT_EQ(result, false);
216 }
217
218 /**
219 * @tc.name: BundleManagerAdapter_QueryAbilityInfos_0100
220 * @tc.desc: test QueryAbilityInfos failed with param is invalid
221 * @tc.type: FUNC
222 * @tc.require:
223 */
224 HWTEST_F(BundleManagerModuleTest, BundleManagerAdapter_QueryAbilityInfos_0100, TestSize.Level1)
225 {
226 Want want;
227 std::vector<AbilityInfo> abilityInfos;
228 bool result = BundleManagerAdapter::GetInstance()->QueryAbilityInfos(want, FLAGS, USER_ID, abilityInfos);
229 ASSERT_EQ(result, false);
230 }
231
232 /**
233 * @tc.name: BundleManagerAdapter_ResetProxy_0100
234 * @tc.desc: test ResetProxy branch of remove proxy.
235 * @tc.type: FUNC
236 * @tc.require:
237 */
238 HWTEST_F(BundleManagerModuleTest, BundleManagerAdapter_ResetProxy_0100, TestSize.Level1)
239 {
240 auto bundleManagerAdapterSptr = BundleManagerAdapter::GetInstance();
241 ErrCode result = bundleManagerAdapterSptr->Connect();
242 ASSERT_EQ(result, ERR_OK);
243 ASSERT_NE(bundleManagerAdapterSptr->proxy_, nullptr);
244 auto sptr = bundleManagerAdapterSptr->proxy_->AsObject();
245 ASSERT_NE(nullptr, sptr);
246 bundleManagerAdapterSptr->ResetProxy(sptr);
247 ASSERT_EQ(bundleManagerAdapterSptr->proxy_, nullptr);
248 }
249
250 /**
251 * @tc.name: BundleManagerProxy_SendTransactCmd_0100
252 * @tc.desc: test SendTransactCmd failed with param is invalid
253 * @tc.type: FUNC
254 * @tc.require:
255 */
256 HWTEST_F(BundleManagerModuleTest, BundleManagerProxy_SendTransactCmd_0100, TestSize.Level1)
257 {
258 sptr<ISystemAbilityManager> systemAbilityManager =
259 SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
260 ASSERT_NE(systemAbilityManager, nullptr);
261 sptr<IRemoteObject> remoteObj = systemAbilityManager->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
262 ASSERT_NE(remoteObj, nullptr);
263 auto bundleManagerAdapterProxy = std::make_shared<BundleManagerAdapterProxy>(remoteObj);
264 ASSERT_NE(bundleManagerAdapterProxy, nullptr);
265
266 MessageParcel reply;
267 MessageParcel data;
268 EXPECT_EQ(bundleManagerAdapterProxy->SendTransactCmd(
269 BundleMgrInterfaceCode::QUERY_ABILITY_INFOS_MUTI_PARAM, data, reply), false);
270 }
271
272 /**
273 * @tc.name: BundleManagerProxy_SendData_0100
274 * @tc.desc: test func SendData
275 * @tc.type: FUNC
276 * @tc.require:
277 */
278 HWTEST_F(BundleManagerModuleTest, BundleManagerProxy_SendData_0100, TestSize.Level1)
279 {
280 ASSERT_NE(g_bundleManagerAdapterProxyRemoteNull, nullptr);
281 void *buffer = nullptr;
282
283 bool result = g_bundleManagerAdapterProxyRemoteNull->SendData(buffer, 10, nullptr);
284 EXPECT_EQ(result, false);
285
286 result = g_bundleManagerAdapterProxyRemoteNull->SendData(buffer, 0, "test_data");
287 EXPECT_EQ(result, false);
288
289 // max value malloc failed
290 result = g_bundleManagerAdapterProxyRemoteNull->SendData(buffer, -1, "test_data");
291 EXPECT_EQ(result, false);
292
293 result = g_bundleManagerAdapterProxyRemoteNull->SendData(buffer, 10, "test_data");
294 EXPECT_EQ(result, true);
295 }
296
297 /**
298 * @tc.name: BundleManagerProxy_GetVectorFromParcelIntelligent_0100
299 * @tc.desc: test GetVectorFromParcelIntelligent failed with param is invalid
300 * @tc.type: FUNC
301 * @tc.require:
302 */
303 HWTEST_F(BundleManagerModuleTest, BundleManagerProxy_GetVectorFromParcelIntelligent_0100, TestSize.Level1)
304 {
305 ASSERT_NE(g_bundleManagerAdapterProxyRemoteNull, nullptr);
306 MessageParcel data;
307 std::vector<AbilityInfo> abilityInfos;
308
309 bool result =g_bundleManagerAdapterProxyRemoteNull->GetVectorFromParcelIntelligent<AbilityInfo>(
310 BundleMgrInterfaceCode::QUERY_ABILITY_INFOS_MUTI_PARAM, data, abilityInfos);
311 EXPECT_EQ(result, false);
312 }
313
314 /**
315 * @tc.name: BundleManagerProxy_InnerGetVectorFromParcelIntelligent_0100
316 * @tc.desc: test func failed with param is invalid
317 * @tc.type: FUNC
318 * @tc.require:
319 */
320 HWTEST_F(BundleManagerModuleTest, BundleManagerProxy_InnerGetVectorFromParcelIntelligent_0100, TestSize.Level1)
321 {
322 ASSERT_NE(g_bundleManagerAdapterProxyRemoteNull, nullptr);
323 MessageParcel reply;
324 std::vector<AbilityInfo> abilityInfos;
325
326 bool result = g_bundleManagerAdapterProxyRemoteNull->InnerGetVectorFromParcelIntelligent<AbilityInfo>(
327 reply, abilityInfos);
328 EXPECT_EQ(result, false);
329 }
330
331 /**
332 * @tc.name: BundleManagerAdapter_ParseStr_0100
333 * @tc.desc: test ParseStr
334 * @tc.type: FUNC
335 * @tc.require:
336 */
337 HWTEST_F(BundleManagerModuleTest, BundleManagerAdapter_ParseStr_0100, TestSize.Level1)
338 {
339 // test buf is nullptr.
340 int itemLen = 10;
341 int index = 0;
342 std::string result;
343 EXPECT_EQ(g_bundleManagerAdapterProxyRemoteNull->ParseStr(nullptr, itemLen, index, result), false);
344
345 // test itemLen is invalid.
346 const char *buf = "test";
347 itemLen = -1;
348 EXPECT_EQ(g_bundleManagerAdapterProxyRemoteNull->ParseStr(buf, itemLen, index, result), false);
349
350 // test index is invalid.
351 itemLen = 10;
352 index = -1;
353 EXPECT_EQ(g_bundleManagerAdapterProxyRemoteNull->ParseStr(buf, itemLen, index, result), false);
354
355 // test normal case.
356 itemLen = 4;
357 index = 0;
358 EXPECT_EQ(g_bundleManagerAdapterProxyRemoteNull->ParseStr(buf, itemLen, index, result), true);
359 EXPECT_EQ(result, "test");
360 }
361
362 /**
363 * @tc.name: BundleManagerAdapter_ParseExtensionAbilityInfos_0100
364 * @tc.desc: test ParseExtensionAbilityInfos
365 * @tc.type: FUNC
366 * @tc.require:
367 */
368 HWTEST_F(BundleManagerModuleTest, BundleManagerAdapter_ParseExtensionAbilityInfos_0100, TestSize.Level1)
369 {
370 ASSERT_NE(g_bundleManagerAdapterProxyRemoteNull, nullptr);
371
372 std::vector<ExtensionAbilityInfo> extensionInfos;
373 // test info with normal data.
374 auto testBundleInfo = CreateJson();
375 AddStringToJson(testBundleInfo, "name", "test_name");
376 AddStringToJson(testBundleInfo, "label", "test_label");
377 AddStringToJson(testBundleInfo, "description", "test_description");
378 AddIntToJson(testBundleInfo, "type", 0);
379 AddBoolToJson(testBundleInfo, "visible", true);
380 AddIntToJson(testBundleInfo, "uid", 123);
381
382 auto arrays = CreateJsonArray();
383 AddObjToArray(arrays, testBundleInfo);
384 auto testBundleInfo1 = CreateJson();
385 AddObjToJson(testBundleInfo1, "extensionAbilityInfo", arrays);
386
387 EXPECT_EQ(g_bundleManagerAdapterProxyRemoteNull->ParseExtensionAbilityInfos(
388 testBundleInfo1, extensionInfos), true);
389 }
390
391 /**
392 * @tc.name: BundleManagerAdapter_ParseExtensionAbilityInfos_0200
393 * @tc.desc: test invalid parameter
394 * @tc.type: FUNC
395 * @tc.require:
396 */
397 HWTEST_F(BundleManagerModuleTest, BundleManagerAdapter_ParseExtensionAbilityInfos_0200, TestSize.Level1)
398 {
399 ASSERT_NE(g_bundleManagerAdapterProxyRemoteNull, nullptr);
400
401 std::vector<ExtensionAbilityInfo> extensionInfos;
402 // invalid value
403 auto testBundleInfo = CreateJson();
404 AddIntToJson(testBundleInfo, "name", 1);
405 AddIntToJson(testBundleInfo, "label", 1);
406 AddIntToJson(testBundleInfo, "description", 1);
407 AddStringToJson(testBundleInfo, "type", "testtest");
408 AddStringToJson(testBundleInfo, "visible", "test");
409 AddStringToJson(testBundleInfo, "uid", "123");
410
411 auto arrays1 = CreateJsonArray();
412 AddObjToArray(arrays1, testBundleInfo);
413 auto arrays2 = CreateJsonArray();
414 AddStringToArray(arrays1, "invalidjsonobject");
415 auto testBundleInfo1 = CreateJson();
416 AddObjToJson(testBundleInfo1, "extensionAbilityInfo", arrays1);
417
418 auto testBundleInfo2 = CreateJson();
419 AddObjToJson(testBundleInfo2, "extensionAbilityInfo", arrays2);
420
421 EXPECT_EQ(g_bundleManagerAdapterProxyRemoteNull->ParseExtensionAbilityInfos(
422 testBundleInfo1, extensionInfos), true);
423 EXPECT_EQ(g_bundleManagerAdapterProxyRemoteNull->ParseExtensionAbilityInfos(
424 testBundleInfo2, extensionInfos), true);
425 }
426
427 /**
428 * @tc.name: BundleManagerAdapter_ParseExtensionInfo_0100
429 * @tc.desc: an invalid json string
430 * @tc.type: FUNC
431 * @tc.require:
432 */
433 HWTEST_F(BundleManagerModuleTest, BundleManagerAdapter_ParseExtensionInfo_0100, TestSize.Level1)
434 {
435 ASSERT_NE(g_bundleManagerAdapterProxyRemoteNull, nullptr);
436 ExtensionAbilityInfo extensionInfo;
437
438 EXPECT_EQ(g_bundleManagerAdapterProxyRemoteNull->ParseExtensionInfo("invalidjsonobject", extensionInfo), false);
439 }
440
441 /**
442 * @tc.name: BundleManagerAdapter_ParseExtensionInfo_0200
443 * @tc.desc: an invalid json string
444 * @tc.type: FUNC
445 * @tc.require:
446 */
447 HWTEST_F(BundleManagerModuleTest, BundleManagerAdapter_ParseExtensionInfo_0200, TestSize.Level1)
448 {
449 ASSERT_NE(g_bundleManagerAdapterProxyRemoteNull, nullptr);
450 ExtensionAbilityInfo extensionInfo;
451
452 auto testBundleInfo = CreateJson();
453 AddIntToJson(testBundleInfo, "invalid_name", 1);
454 AddIntToJson(testBundleInfo, "invalid_label", 1);
455 AddIntToJson(testBundleInfo, "invalid_description", 1);
456 AddStringToJson(testBundleInfo, "invalid_type", "testtest");
457 AddStringToJson(testBundleInfo, "invalid_visible", "test");
458 AddStringToJson(testBundleInfo, "invalid_uid", "123");
459 std::string testStr = PackJsonToString(testBundleInfo);
460
461 EXPECT_EQ(g_bundleManagerAdapterProxyRemoteNull->ParseExtensionInfo(testStr, extensionInfo), true);
462 }
463
464 /**
465 * @tc.name: BundleManagerAdapter_QueryExtensionAbilityInfos_0100
466 * @tc.desc: QueryExtensionAbilityInfos
467 * @tc.type: FUNC
468 * @tc.require:
469 */
470 HWTEST_F(BundleManagerModuleTest, BundleManagerAdapter_QueryExtensionAbilityInfos_0100, TestSize.Level1)
471 {
472 ASSERT_NE(g_bundleManagerAdapterProxyRemoteNull, nullptr);
473 Want want;
474 int32_t flag = 1;
475 std::vector<ExtensionAbilityInfo> extensionInfos;
476 EXPECT_EQ(g_bundleManagerAdapterProxyRemoteNull->QueryExtensionAbilityInfos(
477 want, flag, USER_ID, extensionInfos), false);
478 }
479
480 /**
481 * @tc.name: BundleManagerAdapter_QueryExtensionAbilityInfos_0200
482 * @tc.desc: QueryExtensionAbilityInfos
483 * @tc.type: FUNC
484 * @tc.require:
485 */
486 HWTEST_F(BundleManagerModuleTest, BundleManagerAdapter_QueryExtensionAbilityInfos_0200, TestSize.Level1)
487 {
488 ASSERT_NE(g_bundleManagerAdapterProxyRemoteNull, nullptr);
489 Want want;
490 int32_t flag = 1;
491 std::vector<ExtensionAbilityInfo> extensionInfos;
492 EXPECT_EQ(g_bundleManagerAdapterProxyRemoteNull->QueryExtensionAbilityInfos(
493 want, ExtensionAbilityType::BACKUP, flag, USER_ID, extensionInfos), false);
494 }
495