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 "ohos_resource_adapter_impl.h"
17 
18 #include <ctime>
19 #include <securec.h>
20 #include <sstream>
21 #include <cerrno>
22 #include <cstring>
23 #include <unistd.h>
24 #include <vector>
25 #include <fstream>
26 #include <json/json.h>
27 
28 #include "application_context.h"
29 #include "bundle_mgr_proxy.h"
30 #include "extractor.h"
31 #include "if_system_ability_manager.h"
32 #include "iservice_registry.h"
33 #include "locale_config.h"
34 #include "nweb_log.h"
35 #include "ohos_adapter_helper.h"
36 #include "parameter.h"
37 #include "parameters.h"
38 #include "system_ability_definition.h"
39 
40 using namespace OHOS::AbilityBase;
41 
42 namespace {
43 const std::string NWEB_HAP_PATH = "/system/app/com.ohos.nweb/NWeb.hap";
44 const std::string NWEB_HAP_PATH_1 = "/system/app/NWeb/NWeb.hap";
45 const std::string ARKWEBCORE_HAP_SANDBOX_PATH = "/data/storage/el1/bundle/nweb/entry.hap";
46 const std::string PERSIST_ARKWEBCORE_INSTALL_PATH = "persist.arkwebcore.install_path";
47 const std::string NWEB_HAP_PATH_MODULE_UPDATE = "/module_update/ArkWebCore/app/com.ohos.nweb/NWeb.hap";
48 const std::string HAP_REAL_PATH_PREFIX = "/data/app/el1/bundle/public/";
49 const std::string HAP_SANDBOX_PATH_PREFIX = "/data/storage/el1/bundle/nweb/";
50 
51 const std::string NWEB_BUNDLE_NAME = "com.ohos.nweb";
52 const std::string NWEB_PACKAGE = "entry";
53 const std::string RAWFILE_PREFIX = "resources/rawfile/";
54 const std::string BUNDLE_NAME_PREFIX = "bundleName:";
55 const std::string MODULE_NAME_PREFIX = "moduleName:";
56 constexpr uint32_t TM_YEAR_BITS = 9;
57 constexpr uint32_t TM_MON_BITS = 5;
58 constexpr uint32_t TM_MIN_BITS = 5;
59 constexpr uint32_t TM_HOUR_BITS = 11;
60 constexpr uint32_t START_YEAR = 1900;
61 } // namespace
62 
63 namespace OHOS::NWeb {
64 namespace {
GetResourceMgr(const std::string & bundleName,const std::string & moduleName)65 std::shared_ptr<Global::Resource::ResourceManager> GetResourceMgr(
66     const std::string& bundleName, const std::string& moduleName)
67 {
68     std::shared_ptr<AbilityRuntime::ApplicationContext> context =
69         AbilityRuntime::ApplicationContext::GetApplicationContext();
70     if (!context) {
71         WVLOG_E("Failed to get application context.");
72         return nullptr;
73     }
74 
75     if (bundleName.empty() || moduleName.empty()) {
76         return context->GetResourceManager();
77     }
78     auto moduleContext = context->CreateModuleContext(bundleName, moduleName);
79     if (!moduleContext) {
80         WVLOG_E("Failed to crate module context, bundleName: %{public}s, moduleName: %{public}s.",
81             bundleName.c_str(), moduleName.c_str());
82         return nullptr;
83     }
84     return moduleContext->GetResourceManager();
85 }
86 
ParseRawFile(const std::string & rawFile,std::string & bundleName,std::string & moduleName,std::string & fileName)87 bool ParseRawFile(const std::string& rawFile,
88     std::string& bundleName, std::string& moduleName, std::string& fileName)
89 {
90     if (rawFile.substr(0, RAWFILE_PREFIX.size()) != RAWFILE_PREFIX) {
91         WVLOG_D("ParseRawFile failed, rawfile: %{public}s", rawFile.c_str());
92         return false;
93     }
94 
95     std::string subStr = rawFile.substr(RAWFILE_PREFIX.size());
96     if (subStr.substr(0, BUNDLE_NAME_PREFIX.size()) != BUNDLE_NAME_PREFIX) {
97         return false;
98     }
99     subStr = subStr.substr(BUNDLE_NAME_PREFIX.size());
100     size_t pos = subStr.find('/');
101     if (pos == std::string::npos) {
102         WVLOG_D("ParseRawFile bundleName failed, rawfile: %{public}s", rawFile.c_str());
103         return false;
104     }
105     bundleName = subStr.substr(0, pos);
106 
107     subStr = subStr.substr(pos + 1);
108     if (subStr.substr(0, MODULE_NAME_PREFIX.size()) != MODULE_NAME_PREFIX) {
109         return false;
110     }
111     subStr = subStr.substr(MODULE_NAME_PREFIX.size());
112     pos = subStr.find('/');
113     if (pos == std::string::npos) {
114         WVLOG_D("ParseRawFile moduleName failed, rawfile: %{public}s", rawFile.c_str());
115         return false;
116     }
117     moduleName = subStr.substr(0, pos);
118 
119     fileName = subStr.substr(pos + 1);
120     if (fileName.empty()) {
121         WVLOG_D("ParseRawFile fileName failed, rawfile: %{public}s", rawFile.c_str());
122         return false;
123     }
124     return true;
125 }
126 
convertToSandboxPath(const std::string & installPath,const std::string & prefixPath)127 std::string convertToSandboxPath(const std::string& installPath, const std::string& prefixPath)
128 {
129     if (installPath.empty()) {
130         return "";
131     }
132     size_t result = installPath.find(HAP_REAL_PATH_PREFIX);
133     if (result != std::string::npos) {
134         size_t pos = installPath.find_last_of('/');
135         if (pos != std::string::npos && pos != installPath.size() - 1) {
136             return prefixPath + installPath.substr(pos + 1);
137         }
138     }
139     return installPath;
140 }
141 
GetArkWebHapPath(const std::string & arkWebCoreHapPathOverride,std::vector<std::pair<std::string,int>> & errorMessage)142 std::string GetArkWebHapPath(const std::string& arkWebCoreHapPathOverride,
143                              std::vector<std::pair<std::string, int>>& errorMessage)
144 {
145     std::string prefixPath = WEBVIEW_SANDBOX_PATH;
146     if (access(arkWebCoreHapPathOverride.c_str(), F_OK) == 0) {
147         std::string sandboxPath = convertToSandboxPath(arkWebCoreHapPathOverride, prefixPath);
148         if (access(sandboxPath.c_str(), F_OK) == 0) {
149             WVLOG_D("eixt HAP_arkWebCoreHapPathOverride");
150             return sandboxPath;
151         }
152     }
153     errorMessage.emplace_back("access arkWebCoreHapPathOverride path failed", errno);
154 
155     std::string installPath = convertToSandboxPath(
156         OHOS::system::GetParameter(PERSIST_ARKWEBCORE_INSTALL_PATH, ""), prefixPath);
157     if (access(installPath.c_str(), F_OK) == 0) {
158         WVLOG_D("exit install_path,%{public}s", installPath.c_str());
159         return installPath;
160     }
161     errorMessage.emplace_back("access nweb install path failed", errno);
162 
163     if (access(WEBVIEW_SANDBOX_HAP_PATH, F_OK) == 0) {
164         WVLOG_D("exit WEBVIEW_SANDBOX_HAP_PATH");
165         return WEBVIEW_SANDBOX_HAP_PATH;
166     }
167     errorMessage.emplace_back("access arkwebcore hap sandbox path failed", errno);
168     if (access(WEBVIEW_APP_HAP_PATH2, F_OK) == 0) {
169         WVLOG_D("exit WEBVIEW_APP_HAP_PATH2");
170         return WEBVIEW_APP_HAP_PATH2;
171     }
172     errorMessage.emplace_back("access ohos nweb hap path failed", errno);
173     if (access(WEBVIEW_APP_HAP_PATH, F_OK) == 0) {
174         WVLOG_D("exit WEBVIEW_APP_HAP_PATH");
175         return WEBVIEW_APP_HAP_PATH;
176     }
177     errorMessage.emplace_back("access nweb hap path failed", errno);
178     if (access(WEBVIEW_HAP_PATH, F_OK) == 0) {
179         WVLOG_D("exit WEBVIEW_HAP_PATH");
180         return WEBVIEW_HAP_PATH;
181     }
182     errorMessage.emplace_back("access nweb hap module update path failed", errno);
183     return "";
184 }
185 
GetNWebHapPath(const std::string & arkWebCoreHapPathOverride)186 std::string GetNWebHapPath(const std::string& arkWebCoreHapPathOverride)
187 {
188     std::vector<std::pair<std::string, int>> errorMessage;
189     std::string arkWebHapPath = GetArkWebHapPath(arkWebCoreHapPathOverride, errorMessage);
190     if (!arkWebHapPath.empty()) {
191         return arkWebHapPath;
192     }
193 
194     std::string prefixPath = HAP_SANDBOX_PATH_PREFIX;
195     if (access(arkWebCoreHapPathOverride.c_str(), F_OK) == 0) {
196         WVLOG_D("eixt HAP_arkWebCoreHapPathOverride");
197         std::string sandboxPath = convertToSandboxPath(arkWebCoreHapPathOverride, prefixPath);
198         WVLOG_D("sandboxPath,%{public}s", sandboxPath.c_str());
199         if (access(sandboxPath.c_str(), F_OK) == 0) {
200             return sandboxPath;
201         }
202     }
203     errorMessage.emplace_back("access arkWebCoreHapPathOverride path failed", errno);
204 
205     std::string installPath = convertToSandboxPath(
206         OHOS::system::GetParameter(PERSIST_ARKWEBCORE_INSTALL_PATH, ""), prefixPath);
207     WVLOG_D("install_path,%{public}s", installPath.c_str());
208     if (access(installPath.c_str(), F_OK) == 0) {
209         return installPath;
210     }
211     errorMessage.emplace_back("access nweb install path failed", errno);
212 
213     if (access(ARKWEBCORE_HAP_SANDBOX_PATH.c_str(), F_OK) == 0) {
214         WVLOG_D("eixt ARKWEBCORE_HAP_SANDBOX_PATH");
215         return ARKWEBCORE_HAP_SANDBOX_PATH;
216     }
217     errorMessage.emplace_back("access arkwebcore hap sandbox path failed", errno);
218 
219     if (access(NWEB_HAP_PATH.c_str(), F_OK) == 0) {
220         WVLOG_D("eixt NWEB_HAP_PATH");
221         return NWEB_HAP_PATH;
222     }
223     errorMessage.emplace_back("access ohos nweb hap path failed", errno);
224 
225     if (access(NWEB_HAP_PATH_1.c_str(), F_OK) == 0) {
226         WVLOG_D("eixt NWEB_HAP_PATH_1");
227         return NWEB_HAP_PATH_1;
228     }
229     errorMessage.emplace_back("access nweb hap path failed", errno);
230 
231     if (access(NWEB_HAP_PATH_MODULE_UPDATE.c_str(), F_OK) == 0) {
232         WVLOG_D("eixt NWEB_HAP_PATH_MODULE_UPDATE");
233         return NWEB_HAP_PATH_MODULE_UPDATE;
234     }
235     errorMessage.emplace_back("access nweb hap module update path failed", errno);
236     for (const auto& err : errorMessage) {
237         WVLOG_E("%{public}s, errno(%{public}d): %{public}s", err.first.c_str(), err.second, strerror(err.second));
238     }
239     return "";
240 }
241 } // namespace
242 
OhosFileMapperImpl(std::unique_ptr<OHOS::AbilityBase::FileMapper> fileMap,const std::shared_ptr<Extractor> & extractor)243 OhosFileMapperImpl::OhosFileMapperImpl(std::unique_ptr<OHOS::AbilityBase::FileMapper> fileMap,
244     const std::shared_ptr<Extractor>& extractor): extractor_(extractor), fileMap_(std::move(fileMap))
245 {
246 }
247 
GetFd()248 int32_t OhosFileMapperImpl::GetFd()
249 {
250     return -1;
251 }
252 
GetOffset()253 int32_t OhosFileMapperImpl::GetOffset()
254 {
255     return fileMap_ ? fileMap_->GetOffset(): -1;
256 }
257 
GetFileName()258 std::string OhosFileMapperImpl::GetFileName()
259 {
260     return fileMap_ ? fileMap_->GetFileName(): "";
261 }
262 
IsCompressed()263 bool OhosFileMapperImpl::IsCompressed()
264 {
265     return fileMap_ ? fileMap_->IsCompressed(): false;
266 }
267 
GetDataPtr()268 void* OhosFileMapperImpl::GetDataPtr()
269 {
270     return fileMap_ ? fileMap_->GetDataPtr(): nullptr;
271 }
272 
GetDataLen()273 size_t OhosFileMapperImpl::GetDataLen()
274 {
275     return fileMap_ ? fileMap_->GetDataLen(): 0;
276 }
277 
UnzipData(uint8_t ** dest,size_t & len)278 bool OhosFileMapperImpl::UnzipData(uint8_t** dest, size_t& len)
279 {
280     if (extractor_ && IsCompressed()) {
281         std::unique_ptr<uint8_t[]> data;
282         bool result = extractor_->UnzipData(std::move(fileMap_), data, len);
283         if (result) {
284             *dest = data.release();
285         }
286         return result;
287     }
288     return false;
289 }
290 
291 std::string OhosResourceAdapterImpl::arkWebCoreHapPathOverride_ = "";
OhosResourceAdapterImpl(const std::string & hapPath)292 OhosResourceAdapterImpl::OhosResourceAdapterImpl(const std::string& hapPath)
293 {
294     Init(hapPath);
295 }
296 
Init(const std::string & hapPath)297 void OhosResourceAdapterImpl::Init(const std::string& hapPath)
298 {
299     bool newCreate = false;
300     std::string nwebHapPath = GetNWebHapPath(arkWebCoreHapPathOverride_);
301     if (!nwebHapPath.empty()) {
302         sysExtractor_ = ExtractorUtil::GetExtractor(nwebHapPath, newCreate);
303         if (!sysExtractor_) {
304             WVLOG_E("RuntimeExtractor create failed for %{public}s", nwebHapPath.c_str());
305         }
306     }
307     if (hapPath.empty()) {
308         return;
309     }
310     std::string loadPath = ExtractorUtil::GetLoadFilePath(hapPath);
311     extractor_ = ExtractorUtil::GetExtractor(loadPath, newCreate);
312     if (!extractor_) {
313         WVLOG_E("RuntimeExtractor create failed for %{public}s", hapPath.c_str());
314     }
315 }
316 
GetRawFileData(const std::string & rawFile,size_t & len,uint8_t ** dest,bool isSys)317 bool OhosResourceAdapterImpl::GetRawFileData(const std::string& rawFile, size_t& len,
318     uint8_t** dest, bool isSys)
319 {
320     std::unique_ptr<uint8_t[]> data;
321     bool result;
322     if (isSys) {
323         result =  GetRawFileData(sysExtractor_, rawFile, len, data);
324         if (result) {
325             *dest = data.release();
326         }
327         return result;
328     }
329     std::string bundleName;
330     std::string moduleName;
331     std::string fileName;
332     if (ParseRawFile(rawFile, bundleName, moduleName, fileName)) {
333         auto resourceManager = GetResourceMgr(bundleName, moduleName);
334         if (!resourceManager) {
335             result = GetRawFileData(extractor_, rawFile, len, data);
336             if (result) {
337                 *dest = data.release();
338             }
339             return result;
340         }
341         auto state = resourceManager->GetRawFileFromHap(fileName, len, data);
342         if (state != Global::Resource::SUCCESS) {
343             WVLOG_E("GetRawFileFromHap failed, state: %{public}d, fileName: %{public}s", state, fileName.c_str());
344             result = GetRawFileData(extractor_, rawFile, len, data);
345             if (result) {
346                 *dest = data.release();
347             }
348             return result;
349         }
350         *dest = data.release();
351         return true;
352     }
353 
354     result = GetRawFileData(extractor_, rawFile, len, data);
355     if (result) {
356         *dest = data.release();
357     }
358     return result;
359 }
360 
GetResourceString(const std::string & bundleName,const std::string & moduleName,const int32_t resId,std::string & result)361 bool OhosResourceAdapterImpl::GetResourceString(const std::string& bundleName,
362     const std::string& moduleName, const int32_t resId, std::string& result)
363 {
364     auto resourceManager = GetResourceMgr(bundleName, moduleName);
365     if (!resourceManager) {
366         return false;
367     }
368     if (resourceManager->GetStringById(resId, result) == Global::Resource::SUCCESS) {
369         return true;
370     }
371     return false;
372 }
373 
GetRawFileMapper(const std::string & rawFile,bool isSys)374 std::shared_ptr<OhosFileMapper> OhosResourceAdapterImpl::GetRawFileMapper(const std::string& rawFile,
375     bool isSys)
376 {
377     return GetRawFileMapper(isSys? sysExtractor_: extractor_, rawFile);
378 }
379 
IsRawFileExist(const std::string & rawFile,bool isSys)380 bool OhosResourceAdapterImpl::IsRawFileExist(const std::string& rawFile, bool isSys)
381 {
382     return HasEntry(isSys? sysExtractor_: extractor_, rawFile);
383 }
384 
GetRawFileLastModTime(const std::string & rawFile,uint16_t & date,uint16_t & time,bool isSys)385 bool OhosResourceAdapterImpl::GetRawFileLastModTime(const std::string& rawFile,
386     uint16_t& date, uint16_t& time, bool isSys)
387 {
388     FileInfo info;
389     if (GetFileInfo(isSys? sysExtractor_: extractor_, rawFile, info)) {
390         date = info.lastModDate;
391         time = info.lastModTime;
392         return true;
393     }
394     return false;
395 }
396 
GetRawFileLastModTime(const std::string & rawFile,time_t & time,bool isSys)397 bool OhosResourceAdapterImpl::GetRawFileLastModTime(const std::string& rawFile, time_t& time, bool isSys)
398 {
399     FileInfo info;
400     if (GetFileInfo(isSys? sysExtractor_: extractor_, rawFile, info)) {
401         uint16_t modifiedDate = info.lastModDate;
402         uint16_t modifiedTime = info.lastModTime;
403         struct tm newTime;
404         newTime.tm_year = ((modifiedDate >> TM_YEAR_BITS) & 0x7f) + START_YEAR;
405         newTime.tm_mon = (modifiedDate >> TM_MON_BITS) & 0xf;
406         newTime.tm_mday = modifiedDate & 0x1f;
407         newTime.tm_hour = (modifiedTime >> TM_HOUR_BITS) & 0x1f;
408         newTime.tm_min = (modifiedTime >> TM_MIN_BITS) & 0x2f;
409         newTime.tm_sec = (modifiedTime << 1) & 0x1f;
410         newTime.tm_isdst = 0;
411         time = mktime(&newTime);
412         return true;
413     }
414     return false;
415 }
416 
417 // static
HasEntry(const std::shared_ptr<OHOS::AbilityBase::Extractor> & manager,const std::string & rawFile)418 bool OhosResourceAdapterImpl::HasEntry(const std::shared_ptr<OHOS::AbilityBase::Extractor>& manager,
419     const std::string& rawFile)
420 {
421     if (!manager) {
422         return false;
423     }
424     return manager->HasEntry(rawFile);
425 }
426 
GetFileInfo(const std::shared_ptr<OHOS::AbilityBase::Extractor> & manager,const std::string & rawFile,OHOS::AbilityBase::FileInfo & info)427 bool OhosResourceAdapterImpl::GetFileInfo(const std::shared_ptr<OHOS::AbilityBase::Extractor>& manager,
428     const std::string& rawFile, OHOS::AbilityBase::FileInfo& info)
429 {
430     if (!manager) {
431         return false;
432     }
433     return manager->GetFileInfo(rawFile, info);
434 }
435 
GetModuleName(const char * configStr,size_t len)436 std::string OhosResourceAdapterImpl::GetModuleName(const char *configStr, size_t len)
437 {
438     if (configStr == nullptr) {
439         return std::string();
440     }
441     std::string config(configStr, len);
442     static const char *key = "\"moduleName\"";
443     auto idx = config.find(key);
444     if (idx == std::string::npos) {
445         return std::string();
446     }
447     auto start = config.find("\"", idx + strlen(key));
448     if (start == std::string::npos) {
449         return std::string();
450     }
451     auto end = config.find("\"", start + 1);
452     if (end == std::string::npos || end < start + 1) {
453         return std::string();
454     }
455 
456     std::string retStr = std::string(configStr + start + 1, end - start - 1);
457     return retStr;
458 }
459 
ParseModuleName(const std::shared_ptr<Extractor> & manager)460 std::string OhosResourceAdapterImpl::ParseModuleName(const std::shared_ptr<Extractor> &manager)
461 {
462     if (manager == nullptr) {
463         return std::string();
464     }
465     std::unique_ptr<uint8_t[]> configBuf;
466     size_t len;
467     bool ret = manager->ExtractToBufByName("config.json", configBuf, len);
468     if (!ret) {
469         WVLOG_E("failed to get config data from ability");
470         return std::string();
471     }
472     // parse config.json
473     std::string mName = GetModuleName(reinterpret_cast<char *>(configBuf.get()), len);
474     if (mName.size() == 0) {
475         WVLOG_E("parse moduleName from config.json error");
476         return std::string();
477     }
478     return mName;
479 }
480 
GetRawFileData(const std::shared_ptr<Extractor> & manager,const std::string & rawFile,size_t & len,std::unique_ptr<uint8_t[]> & dest)481 bool OhosResourceAdapterImpl::GetRawFileData(const std::shared_ptr<Extractor>& manager,
482     const std::string& rawFile, size_t& len, std::unique_ptr<uint8_t[]>& dest)
483 {
484     if (!manager) {
485         return false;
486     }
487     if (manager->IsStageModel()) {
488         return manager->ExtractToBufByName(rawFile, dest, len);
489     }
490     std::string moduleName = OhosResourceAdapterImpl::ParseModuleName(manager);
491     std::string rawFilePath("assets/");
492     rawFilePath.append(moduleName);
493     rawFilePath.append("/");
494     rawFilePath.append(rawFile);
495     WVLOG_E("fa filepath:%{public}s", rawFilePath.c_str());
496     return manager->ExtractToBufByName(rawFilePath, dest, len);
497 }
498 
GetRawFileMapper(const std::shared_ptr<OHOS::AbilityBase::Extractor> & manager,const std::string & rawFile)499 std::shared_ptr<OhosFileMapper> OhosResourceAdapterImpl::GetRawFileMapper(
500     const std::shared_ptr<OHOS::AbilityBase::Extractor>& manager,
501     const std::string& rawFile)
502 {
503     if (!manager) {
504         return nullptr;
505     }
506     std::unique_ptr<OHOS::AbilityBase::FileMapper> fileMap;
507     auto& systemPropertiesAdapter = OhosAdapterHelper::GetInstance().GetSystemPropertiesInstance();
508     if (systemPropertiesAdapter.GetWebOptimizationValue()) {
509         fileMap = manager->GetMmapData(rawFile);
510     } else {
511         fileMap = manager->GetData(rawFile);
512     }
513     if (fileMap == nullptr) {
514         return nullptr;
515     }
516     bool isCompressed = fileMap->IsCompressed();
517     return std::make_shared<OhosFileMapperImpl>(std::move(fileMap), isCompressed ? manager: nullptr);
518 }
519 
GetArkWebVersion()520 std::string OhosResourceAdapterImpl::GetArkWebVersion()
521 {
522     const std::string hapPaths[] = {
523         "/module_update/ArkWebCore/app/com.huawei.hmos.arkwebcore/ArkWebCore.hap",
524         "/system/app/com.ohos.arkwebcore/ArkWebCore.hap"
525     };
526     const std::string packInfoPath = "pack.info";
527 
528     for (const auto& hapPath : hapPaths) {
529         OHOS::AbilityBase::Extractor extractor(hapPath);
530         if (!extractor.Init()) {
531             WVLOG_E("Failed to initialize extractor for HAP file: %{public}s", hapPath.c_str());
532             continue;
533         }
534 
535         std::ostringstream contentStream;
536         bool ret = extractor.ExtractByName(packInfoPath, contentStream);
537         if (!ret) {
538             WVLOG_E("Failed to extract pack.info from HAP: %{public}s", hapPath.c_str());
539             continue;
540         }
541 
542         std::string configContent = contentStream.str();
543 
544         Json::Value root;
545         Json::Reader reader;
546         if (!reader.parse(configContent, root)) {
547             WVLOG_E("Failed to parse pack.info from HAP: %{public}s", hapPath.c_str());
548             continue;
549         }
550 
551         if (root.isMember("summary") &&
552             root["summary"].isMember("app") &&
553             root["summary"]["app"].isMember("version") &&
554             root["summary"]["app"]["version"].isMember("name")) {
555             return root["summary"]["app"]["version"]["name"].asString();
556         }
557 
558         WVLOG_E("Version information not found in pack.info from HAP: %{public}s", hapPath.c_str());
559     }
560 
561     WVLOG_E("Failed to get ArkWeb version from any of the specified paths");
562     return "";
563 }
564 
SetArkWebCoreHapPathOverride(const std::string & hapPath)565 void OhosResourceAdapterImpl::SetArkWebCoreHapPathOverride(const std::string& hapPath)
566 {
567     arkWebCoreHapPathOverride_ = hapPath;
568 }
569 
GetSystemLanguage()570 std::string OhosResourceAdapterImpl::GetSystemLanguage()
571 {
572     return OHOS::Global::I18n::LocaleConfig::GetSystemLanguage();
573 }
574 
575 }  // namespace OHOS::NWeb
576