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