diff --git a/adapter/ohos/Compressor.java b/adapter/ohos/Compressor.java index d4f5158d11a5cb6048959fda0d1a60422ba6fb42..ae81f35eb41d61a8426a827b0f11f59f8ebfbd1c 100644 --- a/adapter/ohos/Compressor.java +++ b/adapter/ohos/Compressor.java @@ -185,6 +185,7 @@ public class Compressor { private static final String BACKUP_PREFIX = "backup"; private static final int QUERY_SCHEMES_CHECK_COUNT = 50; private static final int QUERY_SCHEMES_CHECK_MIN_API_VERSION = 21; + private static final int DEDUPLICATE_HAR_CHECK_MIN_API_VERSION = 21; private static final int MIN_API_VERSION_ERROR_VALUE = -1; // set timestamp to get fixed MD5 @@ -611,6 +612,12 @@ public class Compressor { LOG.error(PackingToolErrMsg.COMPRESS_HSP_FAILED.toString("Module type must be shared.")); throw new BundleException("Compress hsp failed."); } + // check deduplicateHar + if (!checkDeduplicateHar(jsonString)) { + LOG.error(PackingToolErrMsg.COMPRESS_HSP_FAILED.toString( + "Check the deduplicateHar in the Stage module failed.")); + throw new BundleException("Compress hsp failed."); + } } if (!checkAppPlugin(utility)) { LOG.error(PackingToolErrMsg.COMPRESS_HSP_FAILED.toString("plugin package packaging failed.")); @@ -1088,6 +1095,12 @@ public class Compressor { "Check the querySchemes parameter in the Stage module failed.")); return false; } + // check deduplicateHar + if (!checkDeduplicateHar(jsonString)) { + LOG.error(PackingToolErrMsg.CHECK_STAGE_HAP_FAILED.toString( + "Check the deduplicateHar in the Stage module failed.")); + return false; + } return true; } @@ -1147,12 +1160,15 @@ public class Compressor { private static boolean checkQuerySchemes(String jsonString) throws BundleException { int minAPIVersion = ModuleJsonUtil.getMinAPIVersion(jsonString); - minAPIVersion = (minAPIVersion == MIN_API_VERSION_ERROR_VALUE) ? QUERY_SCHEMES_CHECK_MIN_API_VERSION : minAPIVersion; + if (minAPIVersion == MIN_API_VERSION_ERROR_VALUE || minAPIVersion >= QUERY_SCHEMES_CHECK_MIN_API_VERSION) { + return true; + } List querySchemes = ModuleJsonUtil.getQuerySchemes(jsonString); int querySchemesCount = querySchemes.size(); - if (querySchemesCount > QUERY_SCHEMES_CHECK_COUNT && minAPIVersion < QUERY_SCHEMES_CHECK_MIN_API_VERSION) { + if (querySchemesCount > QUERY_SCHEMES_CHECK_COUNT) { String errMsg = "The number of querySchemes in the Hap(entry) exceeds " + QUERY_SCHEMES_CHECK_COUNT + - ", and the minAPIVersion is less than " + QUERY_SCHEMES_CHECK_MIN_API_VERSION; + ", and the minAPIVersion(" + minAPIVersion + ") is less than " + + QUERY_SCHEMES_CHECK_MIN_API_VERSION; LOG.error(PackingToolErrMsg.CHECK_STAGE_HAP_FAILED.toString(errMsg)); return false; } @@ -1254,6 +1270,23 @@ public class Compressor { return true; } + private static boolean checkDeduplicateHar(String jsonString) throws BundleException { + int minAPIVersion = ModuleJsonUtil.getMinAPIVersion(jsonString); + if (minAPIVersion == MIN_API_VERSION_ERROR_VALUE || minAPIVersion >= DEDUPLICATE_HAR_CHECK_MIN_API_VERSION) { + return true; + } + boolean deduplicateHar = ModuleJsonUtil.getDeduplicateHar(jsonString); + if (deduplicateHar) { + String moduleName = ModuleJsonUtil.parseStageModuleName(jsonString); + String errMsg = "The deduplicateHar of module " + moduleName + " is true, " + + "and the minAPIVersion(" + minAPIVersion + ") is less than " + + DEDUPLICATE_HAR_CHECK_MIN_API_VERSION; + LOG.error(PackingToolErrMsg.CHECK_DEDUPLICATE_HAR_FAILED.toString(errMsg)); + return false; + } + return true; + } + private static boolean checkFAHap(Utility utility) throws BundleException { Optional optional = FileUtils.getFileContent(utility.getJsonPath()); String jsonString = optional.get(); diff --git a/adapter/ohos/ModuleJsonUtil.java b/adapter/ohos/ModuleJsonUtil.java index 0a1b9bd86e4e618cc3b551521dbcf828352dedfe..a692fbd07213885fc47a14550111d894cda17359 100644 --- a/adapter/ohos/ModuleJsonUtil.java +++ b/adapter/ohos/ModuleJsonUtil.java @@ -109,6 +109,7 @@ class ModuleJsonUtil { private static final String PROXY_DATA = "proxyData"; private static final String PROXY_URI = "uri"; private static final String QUERY_SCHEMES = "querySchemes"; + private static final String DEDUPLICATE_HAR = "deduplicateHar"; private static final String CONTINUE_TYPE = "continueType"; private static final String CONTINUE_BUNDLE_NAME = "continueBundleName"; private static final String MULTI_APP_MODE = "multiAppMode"; @@ -1741,6 +1742,21 @@ class ModuleJsonUtil { return querySchemes; } + /** + * get deduplicateHar from json file. + * + * @param jsonString is the json String of module.json + * @return deduplicateHar value + */ + public static boolean getDeduplicateHar(String jsonString) throws BundleException { + boolean deduplicateHar = false; + JSONObject moduleObj = getModuleObj(jsonString); + if (!moduleObj.containsKey(DEDUPLICATE_HAR)) { + return deduplicateHar; + } + return moduleObj.getBoolean(DEDUPLICATE_HAR); + } + /** * Gets the minAPIVersion from a {@code module.json} string. *

diff --git a/adapter/ohos/PackingToolErrMsg.java b/adapter/ohos/PackingToolErrMsg.java index f6e9e66de2e1906f054db728603bdeb929ec8a8c..961239281878f4645390b1e4694d20b45e611690 100644 --- a/adapter/ohos/PackingToolErrMsg.java +++ b/adapter/ohos/PackingToolErrMsg.java @@ -835,6 +835,16 @@ public class PackingToolErrMsg { .setCause("%s") .build(); + /** + * CHECK_HSP_DEDUPLICATE_HAR_FAILED + */ + public static final ErrorMsg CHECK_DEDUPLICATE_HAR_FAILED = ErrorMsg.getPackingToolErrBuilder() + .setTypeCode("12") + .setErrCode("054") + .setDescription("Check deduplicateHar field failed.") + .setCause("%s") + .build(); + // module json check error /** * PARSE_JSON_OBJECT_EXCEPTION diff --git a/packing_tool/frameworks/include/json/module_json.h b/packing_tool/frameworks/include/json/module_json.h index b7f5eee8bffb9c7aa7d08d563469b0cc61267e94..04bd57e7ee7a14cedd2cdf2ec4243c59307dd57d 100644 --- a/packing_tool/frameworks/include/json/module_json.h +++ b/packing_tool/frameworks/include/json/module_json.h @@ -206,6 +206,7 @@ public: bool GetQuerySchemes(std::list& querySchemes); bool GetQuerySchemesByModuleObj(std::unique_ptr& moduleObj, std::list& querySchemes); bool GetQuerySchemesByArray(std::unique_ptr& querySchemesObj, std::list& querySchemes); + bool GetDeduplicateHar(bool &deduplicateHar); bool IsModuleAtomicServiceValid(); bool CheckEntryInAtomicService(); @@ -213,6 +214,7 @@ public: bool CheckStageAsanTsanEnabledValid(); bool CheckStageAtomicService(); bool CheckQuerySchemes(); + bool CheckDeduplicateHar(); bool CheckStageOverlayCfg(); bool GetGenerateBuildHash(bool& generateBuildHash); diff --git a/packing_tool/frameworks/src/hap_packager.cpp b/packing_tool/frameworks/src/hap_packager.cpp index 24a53876bdb599aed501dc1aa79f483fb89898a1..64c1f94d4205503c337ae7185ef575456cf8274f 100644 --- a/packing_tool/frameworks/src/hap_packager.cpp +++ b/packing_tool/frameworks/src/hap_packager.cpp @@ -428,6 +428,11 @@ bool HapPackager::CheckStageHap(const std::string &jsonPath) return false; } + if (!moduleJson_.CheckDeduplicateHar()) { + LOGE("CheckDeduplicateHar failed."); + return false; + } + return true; } diff --git a/packing_tool/frameworks/src/hsp_packager.cpp b/packing_tool/frameworks/src/hsp_packager.cpp index 652857d436f228aa057b59ab7a44eb8c0efeb18b..2eab73b25ff22b18557110f59ecd0c43859c3da5 100644 --- a/packing_tool/frameworks/src/hsp_packager.cpp +++ b/packing_tool/frameworks/src/hsp_packager.cpp @@ -140,7 +140,7 @@ bool HspPackager::IsVerifyValidInHspMode() return false; } } - + std::string outPath = ""; std::string forceRewrite = ""; it = parameterMap_.find(Constants::PARAM_OUT_PATH); @@ -237,6 +237,10 @@ bool HspPackager::CompressHsp() LOGE("module type must be shared."); return false; } + if (!moduleJson_.CheckDeduplicateHar()) { + LOGE("CheckDeduplicateHar failed."); + return false; + } } if (!CompressHspMode(jsonPath_) || !BuildHash(buildHashFinish_, generateBuildHash_, parameterMap_, jsonPath_)) { return false; @@ -275,7 +279,7 @@ bool HspPackager::CompressHspMode(const std::string &jsonPath) return false; } } - + if (!AddCommonFileOrDirectoryToZip(Constants::PARAM_PROFILE_PATH, Constants::PROFILE_NAME)) { return false; } diff --git a/packing_tool/frameworks/src/json/module_json.cpp b/packing_tool/frameworks/src/json/module_json.cpp index c91509e6fafc24bbb7b1c1f3d607b2eca486b794..587c029d742a58430edb748ef4be591b1db09727 100644 --- a/packing_tool/frameworks/src/json/module_json.cpp +++ b/packing_tool/frameworks/src/json/module_json.cpp @@ -34,6 +34,8 @@ const std::string MIN_API_VERSION = "minAPIVersion"; const std::string QUERY_SCHEMES = "querySchemes"; const int32_t QUERY_SCHEMES_CHECK_COUNT = 50; const int32_t QUERY_SCHEMES_CHECK_MIN_API_VERSION = 21; +const std::string DEDUPLICATE_HAR = "deduplicateHar"; +const int32_t DEDUPLICATE_HAR_CHECK_MIN_API_VERSION = 21; const std::string TARGET_API_VERSION = "targetAPIVersion"; const std::string API_RELEASE_TYPE = "apiReleaseType"; const std::string DEBUG = "debug"; @@ -1214,7 +1216,7 @@ bool ModuleJson::CheckStageAsanTsanEnabledValid() LOGE("GetStageAsanEnabled or GetStageTsanEnabled failed"); return false; } - + if (asanEnabled && tsanEnabled) { LOGE("asanEnabled and tsanEnabled cannot be true at the same time."); return false; @@ -1244,10 +1246,13 @@ bool ModuleJson::CheckQuerySchemes() int32_t rawMinAPIVersion = -1; GetMinApiVersion(rawMinAPIVersion); int32_t minAPIVersion = rawMinAPIVersion % 1000; + if (minAPIVersion == -1 || minAPIVersion >= QUERY_SCHEMES_CHECK_MIN_API_VERSION) { + return true; + } std::list querySchemes; GetQuerySchemes(querySchemes); int querySchemesCount = querySchemes.size(); - if (querySchemesCount > QUERY_SCHEMES_CHECK_COUNT && minAPIVersion < QUERY_SCHEMES_CHECK_MIN_API_VERSION) { + if (querySchemesCount > QUERY_SCHEMES_CHECK_COUNT) { LOGE("The number of querySchemes in the Hap(entry) exceeds %d, and the minAPIVersion is less than %d", QUERY_SCHEMES_CHECK_COUNT, QUERY_SCHEMES_CHECK_MIN_API_VERSION); return false; @@ -1255,6 +1260,26 @@ bool ModuleJson::CheckQuerySchemes() return true; } +bool ModuleJson::CheckDeduplicateHar() +{ + int32_t rawMinAPIVersion = -1; + GetMinApiVersion(rawMinAPIVersion); + int32_t minAPIVersion = rawMinAPIVersion % 1000; + if (minAPIVersion == -1 || minAPIVersion >= DEDUPLICATE_HAR_CHECK_MIN_API_VERSION) { + return true; + } + bool deduplicateHar = false; + GetDeduplicateHar(deduplicateHar); + if (deduplicateHar) { + std::string moduleName; + GetStageModuleName(moduleName); + LOGE("The deduplicateHar of module %s is true, and the minAPIVersion(%d) is less than %d", + moduleName.c_str(), minAPIVersion, DEDUPLICATE_HAR_CHECK_MIN_API_VERSION); + return false; + } + return true; +} + bool ModuleJson::CheckStageOverlayCfg() { std::string targetModuleName; @@ -1714,5 +1739,26 @@ bool ModuleJson::GetQuerySchemesByArray(std::unique_ptr& querySchemesObj } return true; } + +bool ModuleJson::GetDeduplicateHar(bool &deduplicateHar) +{ + std::unique_ptr moduleObj; + if (!GetModuleObject(moduleObj)) { + LOGE("GetDeduplicateHar() -> GetModuleObject failed!"); + return false; + } + if (!moduleObj) { + LOGE("GetDeduplicateHar() -> Module node is null!"); + return false; + } + if (!moduleObj->Contains(DEDUPLICATE_HAR.c_str())) { + return false; + } + if (moduleObj->GetBool(DEDUPLICATE_HAR.c_str(), &deduplicateHar) != Result::SUCCESS) { + LOGE("Module node get %s bool node failed!", DEDUPLICATE_HAR.c_str()); + return false; + } + return true; +} } // namespace AppPackingTool } // namespace OHOS diff --git a/packing_tool/frameworks/test/unittest/json/module_json_test/module_json_test.cpp b/packing_tool/frameworks/test/unittest/json/module_json_test/module_json_test.cpp index be7a7bcf4e068201134cd8d2c32dc6fd68389604..6af3f82e143b2d0236a3bfe51e4fa6880c924d39 100755 --- a/packing_tool/frameworks/test/unittest/json/module_json_test/module_json_test.cpp +++ b/packing_tool/frameworks/test/unittest/json/module_json_test/module_json_test.cpp @@ -1597,7 +1597,7 @@ const std::string APP_ERROR_QUERY_SCHEMES = "{" "}," "\"module\": {" "\"deviceType\": \"test\"" - "]" + "}" "}"; const std::string MODULE_JSON_STRING_WITH_QUERY_SCHEMES_1 = "{" @@ -1661,6 +1661,42 @@ const std::string MODULE_JSON_STRING_WITH_QUERY_SCHEMES_3 = "{" "]" "}" "}"; + +const std::string MODULE_JSON_STRING_WITH_DEDUPLICATE_HAR_1 = "{" + "\"app\": {" + "\"versionCode\": 1000000," + "\"versionName\": \"test_version_name\"," + "\"minCompatibleVersionCode\": 99," + "\"minAPIVersion\": 20" + "}," + "\"module\": {" + "\"deduplicateHar\": false" + "}" +"}"; + +const std::string MODULE_JSON_STRING_WITH_DEDUPLICATE_HAR_2 = "{" + "\"app\": {" + "\"versionCode\": 1000000," + "\"versionName\": \"test_version_name\"," + "\"minCompatibleVersionCode\": 99," + "\"minAPIVersion\": 20" + "}," + "\"module\": {" + "\"deduplicateHar\": true" + "}" +"}"; + +const std::string MODULE_JSON_STRING_WITH_DEDUPLICATE_HAR_3 = "{" + "\"app\": {" + "\"versionCode\": 1000000," + "\"versionName\": \"test_version_name\"," + "\"minCompatibleVersionCode\": 99," + "\"minAPIVersion\": 21" + "}," + "\"module\": {" + "\"deduplicateHar\": true" + "}" +"}"; } class ModuleJsonTest : public testing::Test { public: @@ -8680,7 +8716,7 @@ HWTEST_F(ModuleJsonTest, GetQuerySchemes_0200, Function | MediumTest | Level1) std::list querySchemes; OHOS::AppPackingTool::ModuleJson moduleJson; EXPECT_TRUE(moduleJson.ParseFromString(APP_ERROR_QUERY_SCHEMES)); - EXPECT_FALSE(moduleJson.GetQuerySchemes(querySchemes)); + EXPECT_TRUE(moduleJson.GetQuerySchemes(querySchemes)); } /* @@ -8723,7 +8759,7 @@ HWTEST_F(ModuleJsonTest, GetQuerySchemesByModuleObj_0200, Function | MediumTest std::list querySchemes; std::unique_ptr moduleObj = PtJson::Parse("{\"module\": {}}"); OHOS::AppPackingTool::ModuleJson moduleJson; - EXPECT_FALSE(moduleJson.GetQuerySchemesByModuleObj(moduleObj, querySchemes)); + EXPECT_TRUE(moduleJson.GetQuerySchemesByModuleObj(moduleObj, querySchemes)); } /* @@ -8767,7 +8803,7 @@ HWTEST_F(ModuleJsonTest, GetQuerySchemesByArray_0100, Function | MediumTest | Le std::list querySchemes; std::unique_ptr notArray = PtJson::Parse("{\"querySchemes\": \"https\"}"); OHOS::AppPackingTool::ModuleJson moduleJson; - EXPECT_FALSE(moduleJson.GetQuerySchemesByArray(notArray, querySchemes)); + EXPECT_TRUE(moduleJson.GetQuerySchemesByArray(notArray, querySchemes)); } /* @@ -8781,7 +8817,7 @@ HWTEST_F(ModuleJsonTest, GetQuerySchemesByArray_0200, Function | MediumTest | Le std::list querySchemes; std::unique_ptr emptyArray = PtJson::Parse("{\"querySchemes\": []}"); OHOS::AppPackingTool::ModuleJson moduleJson; - EXPECT_FALSE(moduleJson.GetQuerySchemesByArray(emptyArray, querySchemes)); + EXPECT_TRUE(moduleJson.GetQuerySchemesByArray(emptyArray, querySchemes)); } /* @@ -8795,7 +8831,7 @@ HWTEST_F(ModuleJsonTest, GetQuerySchemesByArray_0300, Function | MediumTest | Le std::list querySchemes; std::unique_ptr mixedArray = PtJson::Parse("{\"querySchemes\": 123}"); OHOS::AppPackingTool::ModuleJson moduleJson; - EXPECT_FALSE(moduleJson.GetQuerySchemesByArray(mixedArray, querySchemes)); + EXPECT_TRUE(moduleJson.GetQuerySchemesByArray(mixedArray, querySchemes)); } /* @@ -8807,11 +8843,13 @@ HWTEST_F(ModuleJsonTest, GetQuerySchemesByArray_0300, Function | MediumTest | Le HWTEST_F(ModuleJsonTest, GetQuerySchemesByArray_0400, Function | MediumTest | Level1) { std::list querySchemes; - std::unique_ptr array = PtJson::Parse("{\"querySchemes\": [\"https\", \"ftp\"]}"); + std::unique_ptr moduleObj = PtJson::Parse("{\"querySchemes\": [\"https\", \"ftp\"]}"); + std::unique_ptr array; + moduleObj->GetArray("querySchemes", &array); OHOS::AppPackingTool::ModuleJson moduleJson; EXPECT_TRUE(moduleJson.GetQuerySchemesByArray(array, querySchemes)); EXPECT_EQ(querySchemes.size(), 2); - EXPECT_EQ(querySchemes.front(), "http"); + EXPECT_EQ(querySchemes.front(), "https"); } /* @@ -8857,4 +8895,91 @@ HWTEST_F(ModuleJsonTest, CheckQuerySchemes_0400, Function | MediumTest | Level1) EXPECT_TRUE(moduleJson.ParseFromString(MODULE_JSON_STRING_WITH_QUERY_SCHEMES_2)); EXPECT_FALSE(moduleJson.CheckQuerySchemes()); } + +/* + * @tc.name: GetDeduplicateHar_0100 + * @tc.desc: test GetDeduplicateHar when root is nullptr + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(ModuleJsonTest, GetDeduplicateHar_0100, Function | MediumTest | Level1) +{ + bool deduplicateHar; + OHOS::AppPackingTool::ModuleJson moduleJson; + moduleJson.root_ = nullptr; + EXPECT_FALSE(moduleJson.GetDeduplicateHar(deduplicateHar)); +} + +/* + * @tc.name: GetDeduplicateHar_0200 + * @tc.desc: test GetDeduplicateHar when deduplicateHar field is invalid + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(ModuleJsonTest, GetDeduplicateHar_0200, Function | MediumTest | Level1) +{ + bool deduplicateHar; + OHOS::AppPackingTool::ModuleJson moduleJson; + EXPECT_TRUE(moduleJson.ParseFromString(APP_ERROR_QUERY_SCHEMES)); + EXPECT_FALSE(moduleJson.GetDeduplicateHar(deduplicateHar)); +} + +/* + * @tc.name: GetDeduplicateHar_0300 + * @tc.desc: test GetDeduplicateHar when deduplicateHar field exists and is valid + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(ModuleJsonTest, GetDeduplicateHar_0300, Function | MediumTest | Level1) +{ + bool deduplicateHar; + OHOS::AppPackingTool::ModuleJson moduleJson; + EXPECT_TRUE(moduleJson.ParseFromString(MODULE_JSON_STRING_WITH_DEDUPLICATE_HAR_1)); + EXPECT_TRUE(moduleJson.GetDeduplicateHar(deduplicateHar)); + EXPECT_FALSE(deduplicateHar); +} + +/* + * @tc.name: CheckDeduplicateHar_0100 + * @tc.desc: test CheckDeduplicateHar when root is nullptr + */ +HWTEST_F(ModuleJsonTest, CheckDeduplicateHar_0100, Function | MediumTest | Level1) +{ + OHOS::AppPackingTool::ModuleJson moduleJson; + moduleJson.root_ = nullptr; + EXPECT_TRUE(moduleJson.CheckDeduplicateHar()); +} + +/* + * @tc.name: CheckDeduplicateHar_0200 + * @tc.desc: test CheckDeduplicateHar when deduplicateHar = false + */ +HWTEST_F(ModuleJsonTest, CheckDeduplicateHar_0200, Function | MediumTest | Level1) +{ + OHOS::AppPackingTool::ModuleJson moduleJson; + EXPECT_TRUE(moduleJson.ParseFromString(MODULE_JSON_STRING_WITH_DEDUPLICATE_HAR_1)); + EXPECT_TRUE(moduleJson.CheckDeduplicateHar()); +} + +/* + * @tc.name: CheckDeduplicateHar_0300 + * @tc.desc: test CheckDeduplicateHar when deduplicateHar = true but minAPIVersion >= threshold + */ +HWTEST_F(ModuleJsonTest, CheckDeduplicateHar_0300, Function | MediumTest | Level1) +{ + OHOS::AppPackingTool::ModuleJson moduleJson; + EXPECT_TRUE(moduleJson.ParseFromString(MODULE_JSON_STRING_WITH_DEDUPLICATE_HAR_3)); + EXPECT_TRUE(moduleJson.CheckDeduplicateHar()); +} + +/* + * @tc.name: CheckDeduplicateHar_0400 + * @tc.desc: test CheckDeduplicateHar when deduplicateHar = true and minAPIVersion < threshold + */ +HWTEST_F(ModuleJsonTest, CheckDeduplicateHar_0400, Function | MediumTest | Level1) +{ + OHOS::AppPackingTool::ModuleJson moduleJson; + EXPECT_TRUE(moduleJson.ParseFromString(MODULE_JSON_STRING_WITH_DEDUPLICATE_HAR_2)); + EXPECT_FALSE(moduleJson.CheckDeduplicateHar()); +} }