Init: ohos_electron_hap with real ARM64 .so files

This commit is contained in:
root 2026-05-13 16:42:10 +08:00
commit 20d4e15b42
252 changed files with 21648 additions and 0 deletions

64
.clang-format Normal file
View File

@ -0,0 +1,64 @@
Language: Cpp
# BasedOnStyle: LLVM
ColumnLimit: 120
SortIncludes: CaseSensitive
TabWidth: 4
IndentWidth: 4
UseTab: Never
AccessModifierOffset: -4
ContinuationIndentWidth: 4
IndentCaseBlocks: false
IndentCaseLabels: false
IndentGotoLabels: true
IndentWrappedFunctionNames: false
SortUsingDeclarations: false
NamespaceIndentation: None
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeCaseColon: false
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeRangeBasedForLoopColon: true
SpaceBeforeSquareBrackets: false
SpaceInEmptyBlock: false
SpaceInEmptyParentheses: false
SpacesInAngles: false
SpacesInCStyleCastParentheses: false
SpacesInConditionalStatement: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
AlignTrailingComments: true
AlignAfterOpenBracket: true
AllowShortCaseLabelsOnASingleLine: false
AllowShortEnumsOnASingleLine: true
AllowShortFunctionsOnASingleLine: All
AllowShortIfStatementsOnASingleLine: Never
AllowShortLambdasOnASingleLine: All
AllowShortLoopsOnASingleLine: false
AlwaysBreakTemplateDeclarations: MultiLine
BinPackArguments: true
BinPackParameters: true
BreakBeforeTernaryOperators: true
BreakConstructorInitializers: BeforeColon
BreakInheritanceList: BeforeColon
BreakStringLiterals: true
InsertBraces: false
IndentExternBlock: NoIndent
BreakBeforeBraces: Custom
BraceWrapping:
AfterCaseLabel: false
AfterClass: false
AfterControlStatement: Never
AfterEnum: false
AfterFunction: false
AfterNamespace: false
AfterStruct: false
AfterUnion: false
AfterExternBlock: false
BeforeCatch: false
BeforeElse: false
ReflowComments: true
MaxEmptyLinesToKeep: 2

106
.github/workflows/harmonyos-ci.yml vendored Normal file
View File

@ -0,0 +1,106 @@
name: HarmonyOS CI/CD Pipeline
on:
push:
branches:
- master
- main
- feature/*
- release/*
tags:
- '*'
pull_request:
branches:
- master
- main
- feature/*
- release/*
jobs:
build:
runs-on: ubuntu-latest
container: ghcr.io/sanchuanhehe/harmony-next-pipeline-docker/harmonyos-ci-image:v5.0.4
steps:
# 1. 拉取代码
- name: Checkout code
uses: actions/checkout@v3
# 2. 安装项目依赖
- name: Install dependencies
run: |
cd $GITHUB_WORKSPACE
ohpm install --all
# 3. 构建 HAP 文件
- name: Build HAP
run: |
cd $GITHUB_WORKSPACE
hvigorw clean --no-daemon
hvigorw assembleHap --mode module -p product=default -p buildMode=debug --no-daemon
# 4. 获取构建输出路径
- name: Get build output path
id: get_build_output_path
run: |
cd $GITHUB_WORKSPACE
echo "output_path=$(ls -d $PWD/electron/build/default/outputs/default)" >> $GITHUB_OUTPUT
# 5. 上传构建输出作为 artifact
- name: Upload Build Output
uses: actions/upload-artifact@v4
with:
name: build-output
path: ${{ steps.get_build_output_path.outputs.output_path }}
publish:
needs: build
runs-on: ubuntu-latest
permissions:
contents: write
container: ghcr.io/sanchuanhehe/harmony-next-pipeline-docker/harmonyos-ci-image:latest
if: startsWith(github.ref, 'refs/tags/v')
steps:
# 1. 拉取代码
- name: Checkout code
uses: actions/checkout@v3
# 2. 下载构建输出 artifact
- name: Download Build Output
uses: actions/download-artifact@v4
with:
name: build-output
path: $GITHUB_WORKSPACE/electron/build/default/outputs/default
# 3. 签名 HAP 文件如果存在签名文件和证书文件还有密钥文件和KEY_PASSWORD和KEYSTORE_PASSWORD
- name: Sign HAP
id: sign_hap
if: env.SIGNING_CERT && env.SIGNING_PROFILE && env.SIGNING_KEY
run: |
cd $GITHUB_WORKSPACE
java -jar /harmonyos-tools/command-line-tools/sdk/default/openharmony/toolchains/lib/hap-sign-tool.jar \
sign-app \
-keyAlias "ide_demo_app" \
-signAlg "SHA256withECDSA" \
-mode "localSign" \
-appCertFile "${{ env.SIGNING_CERT }}" \
-profileFile "${{ env.SIGNING_PROFILE }}" \
-inFile "./electron/build/default/outputs/default/electron-default.hap" \
-keystoreFile "${{ env.SIGNING_KEY }}" \
-outFile "./electron/build/default/outputs/default/electron-default-signed.hap" \
-keyPwd "${{ secrets.KEY_PASSWORD }}" \
-keystorePwd "${{ secrets.KEYSTORE_PASSWORD }}" \
-signCode "1"
# 4. 创建 GitHub Release 并上传资产
- name: Create Release and Upload Assets
uses: softprops/action-gh-release@v1
if: startsWith(github.ref, 'refs/tags/v')
with:
name: ${{ github.ref_name }}
files: |
${{ steps.sign_hap.outcome == 'success' && '$GITHUB_WORKSPACE/electron/build/default/outputs/default/electron-default-signed.hap' || '$GITHUB_WORKSPACE/electron/build/default/outputs/default/electron-default-unsigned.hap' }}
draft: false
prerelease: false
env:
GITHUB_TOKEN: ${{ github.token }}

45
.gitignore vendored Normal file
View File

@ -0,0 +1,45 @@
# IDE and Editor files
.vscode/
.idea/
*.swp
*.swo
*~
# OS generated files
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db
# Build artifacts
build/
dist/
out/
.output/
node_modules/
# Logs
*.log
logs/
# Temporary files
*.tmp
*.temp
.cache/
# HarmonyOS specific
.preview/
.hvigor/
oh_modules
# Test coverage
coverage/
# Environment variables
.env
.env.local
.env.development.local
.env.test.local
.env.production.local

15
AppScope/app.json5 Normal file
View File

@ -0,0 +1,15 @@
{
"app": {
"bundleName": "com.huawei.ohos_electron",
"vendor": "example",
"versionCode": 1000000,
"versionName": "1.0.0",
"icon": "$media:app_icon",
"label": "$string:app_name",
"configuration": "$profile:configuration",
"multiAppMode": {
"multiAppModeType": "multiInstance",
"maxCount": 1
}
}
}

View File

@ -0,0 +1,8 @@
{
"string": [
{
"name": "app_name",
"value": "Electron"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

View File

@ -0,0 +1,6 @@
{
"configuration": {
"fontSizeScale": "followSystem",
"fontSizeMaxScale": "1.45"
}
}

301
QUICKSTART.md Normal file
View File

@ -0,0 +1,301 @@
# HarmonyOS Electron 快速上手指南
本指南将帮助您在 30 分钟内快速上手 HarmonyOS Electron 开发。
## 📋 准备清单
### 开发环境
- [ ] DevEco Studio 4.0+
- [ ] HarmonyOS SDK API Level 10+
- [ ] Node.js 16.x+
- [ ] 鸿蒙设备或模拟器
### 必需文件
- [ ] Electron 应用源码或编译产物
- [ ] 开发者证书(可选,用于签名)
## 🚀 5 分钟快速开始
### 步骤 1: 克隆项目
```bash
git clone https://github.com/ohosvscode/ohos_electron_hap.git
cd ohos_electron_hap
```
### 步骤 2: 添加 Electron 应用
将您的 Electron 应用代码放入:
```
web_engine/src/main/resources/resfile/resources/app/
```
### 步骤 3: 构建运行
1. 用 DevEco Studio 打开项目
2. 点击 **Build** → **Build Hap(s)**
3. 点击运行按钮安装到设备
🎉 **恭喜!您的第一个鸿蒙 Electron 应用已经运行起来了!**
## 📖 详细配置教程
### 自定义应用信息
#### 修改应用名称
编辑 `electron/src/main/resources/zh_CN/element/string.json`
```json
{
"string": [
{
"name": "EntryAbility_label",
"value": "我的鸿蒙应用"
}
]
}
```
#### 替换应用图标
1. 准备图标文件(建议 512x512 PNG
2. 替换 `AppScope/resources/base/media/app_icon.png`
3. 重新构建应用
#### 设置启动窗口
编辑 `electron/src/main/module.json5`,在 abilities 中添加:
```json
"metadata": [
{
"name": "ohos.ability.window.width",
"value": "1200"
},
{
"name": "ohos.ability.window.height",
"value": "800"
},
{
"name": "ohos.ability.window.left",
"value": "center"
},
{
"name": "ohos.ability.window.top",
"value": "center"
}
]
```
### 权限配置
#### 基础权限(自动获得)
这些权限会自动获得,无需特殊申请:
- 网络访问
- 获取网络信息
- 后台运行
- 读取剪贴板
#### 需要申请的权限
编辑 `web_engine/src/main/module.json5`,在 `requestPermissions` 中添加:
```json
{
"name": "ohos.permission.CAMERA",
"reason": "$string:camera_reason",
"usedScene": {
"abilities": ["EntryAbility"],
"when": "inuse"
}
}
```
常用权限列表:
- `ohos.permission.CAMERA` - 相机
- `ohos.permission.MICROPHONE` - 麦克风
- `ohos.permission.LOCATION` - 位置
- `ohos.permission.READ_WRITE_DOWNLOAD_DIRECTORY` - 下载目录
### 应用签名
#### 申请开发者证书
1. 访问 [华为开发者联盟](https://developer.huawei.com/)
2. 注册开发者账号
3. 申请 HarmonyOS 应用签名证书
#### 配置签名
1. 在 DevEco Studio 中选择 **File** → **Project Structure**
2. 选择 **Signing Configs**
3. 配置证书文件和密码
4. 重新构建生成已签名 HAP
## 💡 实用示例
### 示例 1: 创建悬浮窗
```javascript
const { BrowserWindow } = require('electron');
function createFloatWindow() {
const floatWindow = new BrowserWindow({
windowInfo: {
type: 'floatWindow'
},
width: 400,
height: 300,
transparent: true,
opacity: 0.9,
frame: false,
alwaysOnTop: true
});
floatWindow.loadURL('https://www.example.com');
return floatWindow;
}
```
### 示例 2: 请求系统权限
```javascript
const { systemPreferences } = require('electron');
async function requestPermissions() {
// 请求相机权限
const cameraGranted = await systemPreferences.requestSystemPermission('camera');
console.log('相机权限:', cameraGranted ? '已授权' : '被拒绝');
// 请求麦克风权限
const micGranted = await systemPreferences.requestSystemPermission('microphone');
console.log('麦克风权限:', micGranted ? '已授权' : '被拒绝');
// 请求目录访问权限
const dirGranted = await systemPreferences.requestDirectoryPermission(null);
console.log('目录权限:', dirGranted ? '已授权' : '被拒绝');
}
// 在应用启动时调用
app.whenReady().then(requestPermissions);
```
### 示例 3: 检查权限状态
```javascript
const { systemPreferences } = require('electron');
function checkPermissionStatus() {
const cameraStatus = systemPreferences.getMediaAccessStatus('camera');
const micStatus = systemPreferences.getMediaAccessStatus('microphone');
console.log('权限状态:', {
camera: cameraStatus, // 'granted', 'denied', 'not-determined'
microphone: micStatus
});
}
```
## 🛠️ 调试技巧
### 渲染进程调试
```javascript
// 在主进程中
const { BrowserWindow } = require('electron');
const win = new BrowserWindow({
webPreferences: {
nodeIntegration: true,
contextIsolation: false
}
});
// 打开开发者工具
win.webContents.openDevTools();
```
### 主进程调试
#### 1. 启用调试模式
编辑 `web_engine/src/main/ets/components/WebWindow.ets`
```typescript
// 添加调试参数
let inspect = '--inspect=9229';
let vec_args = [
'--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
resDir,
inspect // 添加这行
];
```
#### 2. 配置端口转发
```bash
hdc fport tcp:9229 tcp:9229
```
#### 3. Chrome 调试
1. 在 Chrome 中访问:`chrome://inspect`
2. 点击 "Configure..." 添加 `localhost:9229`
3. 启动应用后点击 "inspect" 开始调试
## 🔧 常见问题解决
### 问题 1: 构建失败 "找不到 SO 库"
**解决方案**:
1. 检查 `electron/libs/arm64-v8a/` 目录是否存在
2. 确认 5 个 SO 文件都已正确放置
3. 检查文件权限
### 问题 2: 应用启动崩溃
**解决方案**:
1. 检查 Electron 应用代码是否放在正确位置
2. 确认应用代码已正确编译(如 TypeScript → JavaScript
3. 查看 DevEco Studio 的日志输出
### 问题 3: 权限被拒绝
**解决方案**:
1. 检查 `module.json5` 中的权限声明
2. 确认已正确调用权限请求 API
3. 对于 ACL 权限,确认已申请相应证书
### 问题 4: 三方库不兼容
**解决方案**:
```javascript
// 检查平台
if (process.platform === 'ohos') {
// 鸿蒙平台特殊处理
console.log('运行在 HarmonyOS 上');
}
// 替换不兼容的库
const fs = process.platform === 'ohos'
? require('./ohos-fs-polyfill')
: require('fs');
```
## 📚 进阶学习
### 了解鸿蒙文件系统
```javascript
// 应用数据目录
const userDataPath = '/data/storage/el2/base/files';
const tempPath = '/data/storage/el2/base/temp';
const cachePath = '/data/storage/el2/base/cache';
// 使用 Electron API
const { app } = require('electron');
console.log('用户数据目录:', app.getPath('userData'));
console.log('临时目录:', app.getPath('temp'));
```
### 性能优化建议
1. **预加载重要资源**: 将常用文件放在应用包内
2. **合理使用权限**: 只申请必需的权限
3. **优化启动时间**: 减少首屏加载资源
4. **内存管理**: 及时释放不用的窗口和资源
### 发布准备
1. **测试各种权限场景**
2. **验证多窗口功能**
3. **检查应用图标和名称**
4. **准备应用商店描述**
## 🎯 下一步
- 💬 加入开发者社区交流
---
**需要帮助?**
- 📖 查看完整文档
- 🐛 提交 Issue
- 💬 联系维护团队
祝您开发愉快!🎉

227
README-CN.md Normal file
View File

@ -0,0 +1,227 @@
# HarmonyOS Electron HAP
[English](./README.md) | 简体中文
这是一个基于 HarmonyOS 平台的 Electron 应用程序包HAP项目支持在鸿蒙设备上运行 Electron 应用。
## 项目结构
```
ohos_electron_hap/
├── AppScope/ # 应用范围配置
├── chromium/ # Chromium 模块
├── electron/ # Electron 主模块
├── web_engine/ # Web 引擎组件
├── hvigor/ # 构建工具配置
├── build-profile.json5 # 项目构建配置
├── hvigorfile.ts # 构建脚本
└── oh-package.json5 # 项目依赖配置
```
## 快速开始
### 环境要求
- **DevEco Studio**: 4.0 或更高版本
- **HarmonyOS SDK**: API Level 10 或更高
- **Node.js**: 16.x 或更高版本
- **HDC工具**: 用于设备调试和安装
### 1. 准备资源文件
在开始构建之前,需要准备以下资源:
#### Electron 应用代码
将您的 Electron 应用代码(编译后的产物)放入:
```
web_engine/src/main/resources/resfile/resources/app/
```
### 2. 构建 HAP 包
#### 使用 DevEco Studio
1. 用 DevEco Studio 打开项目
2. 选择 **Build****Build Hap(s)/APP(s)** → **Build Hap(s)**
3. 或点击右上角的运行按钮启动应用
构建完成后,未签名的 HAP 包将保存在:
```
electron/build/default/outputs/default/electron-default-unsigned.hap
```
### 3. 应用签名
为了在设备上正常运行,需要对 HAP 包进行签名:
> 建议使用自动签名验证
1. 申请华为开发者证书
2. 在 DevEco Studio 中配置签名信息
3. 重新构建生成已签名的 HAP 包
详细签名流程请参考:[应用/服务签名-DevEco Studio](https://developer.huawei.com/)
### 4. 安装和运行
#### 通过 DevEco Studio
直接点击运行按钮安装到设备
#### 通过命令行
```bash
hdc app install <已签名hap包路径>
# 示例: hdc app install electron-default-signed.hap
```
## 应用定制
### 修改应用名称
编辑文件:`electron/src/main/resources/zh_CN/element/string.json`
```json
{
"string": [
{
"name": "EntryAbility_label",
"value": "您的应用名称"
}
]
}
```
### 替换应用图标
将新图标文件放入:`AppScope/resources/base/media/`
### 配置启动窗口大小
编辑 `electron/src/main/module.json5`,在 abilities 中添加 metadata
```json
"metadata": [
{
"name": "ohos.ability.window.height",
"value": "800"
},
{
"name": "ohos.ability.window.width",
"value": "800"
},
{
"name": "ohos.ability.window.left",
"value": "center"
},
{
"name": "ohos.ability.window.top",
"value": "center"
}
]
```
## 权限配置
应用权限在 `web_engine/src/main/module.json5` 文件的 `requestPermissions` 字段中配置。
### 基础权限(无需特殊申请)
- `ohos.permission.INTERNET` - 网络访问
- `ohos.permission.GET_NETWORK_INFO` - 获取网络信息
- `ohos.permission.RUNNING_LOCK` - 后台运行锁
- `ohos.permission.PREPARE_APP_TERMINATE` - 应用终止准备
### 需要申请的权限
- `ohos.permission.CAMERA` - 相机权限
- `ohos.permission.MICROPHONE` - 麦克风权限
- `ohos.permission.LOCATION` - 位置权限
- `ohos.permission.READ_WRITE_DOWNLOAD_DIRECTORY` - 下载目录访问
## HarmonyOS 特有功能
### 悬浮窗
```javascript
const { BrowserWindow } = require('electron');
let floatWindow = new BrowserWindow({
windowInfo: {
type: 'floatWindow' // mainWindow, subWindow, floatWindow
},
parent: mainWindow,
x: 100,
y: 100,
width: 800,
height: 600,
transparent: true, // 透明窗口
opacity: 0.5 // 透明度
});
```
### 系统权限请求
```javascript
const { systemPreferences } = require('electron');
// 请求相机权限
systemPreferences.requestSystemPermission('camera').then(granted => {
console.log('Camera permission:', granted);
});
// 请求目录权限
systemPreferences.requestDirectoryPermission(null).then(granted => {
console.log('Directory permission:', granted);
});
```
## 调试
### 渲染进程调试
```javascript
const { BrowserWindow } = require('electron');
const win = new BrowserWindow();
win.webContents.openDevTools();
```
### 主进程调试
1. 在 `web_engine/src/main/ets/components/WebWindow.ets` 中添加调试参数:
```typescript
let inspect = '--inspect=9229';
let vec_args = [..., inspect];
```
2. 配置端口转发:
```bash
hdc fport tcp:9229 tcp:9229
```
3. 在 Chrome 浏览器中访问:`chrome://inspect`
## 应用数据目录
- 用户数据默认存储在:`/data/storage/el2/base/files`
- 应用安装目录:`/data/storage/el1/bundle`
- 数据库目录:`/data/storage/el2/database`
## 常见问题
### 构建失败
1. 检查 SO 库文件是否完整
2. 确认 Electron 应用代码已正确放置
3. 验证权限配置是否正确
### 三方库兼容性
- **C++ addon**: 需要重新编译适配鸿蒙平台
- **平台检测**: 需要适配 `process.platform === 'ohos'`
- **二进制文件**: 可能需要替换为鸿蒙版本
### 权限问题
如果某些 ACL 权限无法获得,可以暂时注释掉相关权限:
```json
// "requestPermissions": [
// {
// "name": "ohos.permission.SYSTEM_FLOAT_WINDOW"
// }
// ]
```
## 贡献指南
1. Fork 本仓库
2. 创建功能分支:`git checkout -b feature/your-feature`
3. 提交更改:`git commit -am 'Add some feature'`
4. 推送到分支:`git push origin feature/your-feature`
5. 提交 Pull Request
## 联系我们
如遇到问题或需要支持,请提交 Issue 或联系维护团队。

227
README.md Normal file
View File

@ -0,0 +1,227 @@
# HarmonyOS Electron HAP
English | [简体中文](./README-CN.md)
A HarmonyOS Application Package (HAP) project based on the HarmonyOS platform that enables running Electron applications on HarmonyOS devices.
## Project Structure
```
ohos_electron_hap/
├── AppScope/ # Application scope configuration
├── chromium/ # Chromium module
├── electron/ # Electron main module
├── web_engine/ # Web engine component
├── hvigor/ # Build tool configuration
├── build-profile.json5 # Project build configuration
├── hvigorfile.ts # Build script
└── oh-package.json5 # Project dependencies configuration
```
## Quick Start
### Environment Requirements
- **DevEco Studio**: 4.0 or higher
- **HarmonyOS SDK**: API Level 10 or higher
- **Node.js**: 16.x or higher
- **HDC Tool**: For device debugging and installation
### 1. Prepare Resource Files
Before starting the build, you need to prepare the following resources:
#### Electron Application Code
Place your Electron application code (compiled artifacts) into:
```
web_engine/src/main/resources/resfile/resources/app/
```
### 2. Build HAP Package
#### Using DevEco Studio
1. Open the project with DevEco Studio
2. Select **Build****Build Hap(s)/APP(s)** → **Build Hap(s)**
3. Or click the run button in the top right corner to launch the application
After building, the unsigned HAP package will be saved at:
```
electron/build/default/outputs/default/electron-default-unsigned.hap
```
### 3. Application Signing
To run normally on devices, the HAP package needs to be signed:
> Recommend using automatic signature verification
1. Apply for Huawei Developer Certificate
2. Configure signing information in DevEco Studio
3. Rebuild to generate signed HAP package
For detailed signing process, please refer to: [Application/Service Signing-DevEco Studio](https://developer.huawei.com/)
### 4. Installation and Running
#### Via DevEco Studio
Click the run button directly to install on device
#### Via Command Line
```bash
hdc app install <signed-hap-package-path>
# Example: hdc app install electron-default-signed.hap
```
## Application Customization
### Modify Application Name
Edit file: `electron/src/main/resources/zh_CN/element/string.json`
```json
{
"string": [
{
"name": "EntryAbility_label",
"value": "Your Application Name"
}
]
}
```
### Replace Application Icon
Place new icon file into: `AppScope/resources/base/media/`
### Configure Startup Window Size
Edit `electron/src/main/module.json5`, add metadata in abilities:
```json
"metadata": [
{
"name": "ohos.ability.window.height",
"value": "800"
},
{
"name": "ohos.ability.window.width",
"value": "800"
},
{
"name": "ohos.ability.window.left",
"value": "center"
},
{
"name": "ohos.ability.window.top",
"value": "center"
}
]
```
## Permission Configuration
Application permissions are configured in the `requestPermissions` field of the `web_engine/src/main/module.json5` file.
### Basic Permissions (No Special Application Required)
- `ohos.permission.INTERNET` - Network access
- `ohos.permission.GET_NETWORK_INFO` - Get network information
- `ohos.permission.RUNNING_LOCK` - Background running lock
- `ohos.permission.PREPARE_APP_TERMINATE` - Application termination preparation
### Permissions Requiring Application
- `ohos.permission.CAMERA` - Camera permission
- `ohos.permission.MICROPHONE` - Microphone permission
- `ohos.permission.LOCATION` - Location permission
- `ohos.permission.READ_WRITE_DOWNLOAD_DIRECTORY` - Download directory access
## HarmonyOS Specific Features
### Floating Window
```javascript
const { BrowserWindow } = require('electron');
let floatWindow = new BrowserWindow({
windowInfo: {
type: 'floatWindow' // mainWindow, subWindow, floatWindow
},
parent: mainWindow,
x: 100,
y: 100,
width: 800,
height: 600,
transparent: true, // Transparent window
opacity: 0.5 // Opacity
});
```
### System Permission Request
```javascript
const { systemPreferences } = require('electron');
// Request camera permission
systemPreferences.requestSystemPermission('camera').then(granted => {
console.log('Camera permission:', granted);
});
// Request directory permission
systemPreferences.requestDirectoryPermission(null).then(granted => {
console.log('Directory permission:', granted);
});
```
## Debugging
### Renderer Process Debugging
```javascript
const { BrowserWindow } = require('electron');
const win = new BrowserWindow();
win.webContents.openDevTools();
```
### Main Process Debugging
1. Add debugging parameters in `web_engine/src/main/ets/components/WebWindow.ets`:
```typescript
let inspect = '--inspect=9229';
let vec_args = [..., inspect];
```
2. Configure port forwarding:
```bash
hdc fport tcp:9229 tcp:9229
```
3. Access in Chrome browser: `chrome://inspect`
## Application Data Directory
- User data stored by default at: `/data/storage/el2/base/files`
- Application installation directory: `/data/storage/el1/bundle`
- Database directory: `/data/storage/el2/database`
## Common Issues
### Build Failure
1. Check if SO library files are complete
2. Confirm Electron application code is correctly placed
3. Verify permission configuration is correct
### Third-party Library Compatibility
- **C++ addon**: Need to recompile for HarmonyOS platform adaptation
- **Platform detection**: Need to adapt `process.platform === 'ohos'`
- **Binary files**: May need to replace with HarmonyOS versions
### Permission Issues
If certain ACL permissions cannot be obtained, you can temporarily comment out related permissions:
```json
// "requestPermissions": [
// {
// "name": "ohos.permission.SYSTEM_FLOAT_WINDOW"
// }
// ]
```
## Contributing
1. Fork this repository
2. Create a feature branch: `git checkout -b feature/your-feature`
3. Commit your changes: `git commit -am 'Add some feature'`
4. Push to the branch: `git push origin feature/your-feature`
5. Submit a Pull Request
## Contact Us
If you encounter issues or need support, please submit an Issue or contact the maintenance team.

44
build-profile.json5 Normal file
View File

@ -0,0 +1,44 @@
{
"app": {
"products": [
{
"name": "default",
"signingConfig": "default",
"compatibleSdkVersion": "5.0.3(15)",
"compatibleSdkVersionStage": "beta6",
"runtimeOS": "HarmonyOS",
"buildOption": {
"nativeLib": {
"collectAllLibs": true
}
}
}
],
"buildModeSet": [
{
"name": "debug",
},
{
"name": "release"
}
]
},
"modules": [
{
"name": "electron",
"srcPath": "./electron",
"targets": [
{
"name": "default",
"applyToProducts": [
"default"
]
}
]
},
{
"name": "web_engine",
"srcPath": "./web_engine"
}
]
}

30
chromium/build-profile.json5 Executable file
View File

@ -0,0 +1,30 @@
{
"apiType": "stageMode",
"buildOption": {
"arkOptions": {
},
},
"buildOptionSet": [
{
"name": "release",
"arkOptions": {
"obfuscation": {
"ruleOptions": {
"enable": true,
"files": [
"./obfuscation-rules.txt"
]
}
}
}
},
],
"targets": [
{
"name": "default"
},
{
"name": "ohosTest",
}
]
}

6
chromium/hvigorfile.ts Executable file
View File

@ -0,0 +1,6 @@
import { hapTasks } from '@ohos/hvigor-ohos-plugin';
export default {
system: hapTasks, /* Built-in plugin of Hvigor. It cannot be modified. */
plugins:[] /* Custom plugin to extend the functionality of Hvigor. */
}

18
chromium/obfuscation-rules.txt Executable file
View File

@ -0,0 +1,18 @@
# Define project specific obfuscation rules here.
# You can include the obfuscation configuration files in the current module's build-profile.json5.
#
# For more details, see
# https://gitee.com/openharmony/arkcompiler_ets_frontend/blob/master/arkguard/README.md
# Obfuscation options:
# -disable-obfuscation: disable all obfuscations
# -enable-property-obfuscation: obfuscate the property names
# -enable-toplevel-obfuscation: obfuscate the names in the global scope
# -compact: remove unnecessary blank spaces and all line feeds
# -remove-log: remove all console.* statements
# -print-namecache: print the name cache that contains the mapping from the old names to new names
# -apply-namecache: reuse the given cache file
# Keep options:
# -keep-property-name: specifies property names that you want to keep
# -keep-global-name: specifies names that you want to keep in the global scope

12
chromium/oh-package.json5 Executable file
View File

@ -0,0 +1,12 @@
{
"license": "",
"devDependencies": {},
"author": "",
"name": "chromium",
"description": "Please describe the basic information.",
"main": "",
"version": "1.0.0",
"dependencies": {
"web_engine": 'file:../web_engine',
}
}

View File

@ -0,0 +1,36 @@
/*
* Copyright (c) 2023-2025 Haitai FangYuan Co., Ltd.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import { WebAbilityStage } from 'web_engine';
export default class MyAbilityStage extends WebAbilityStage {
onCreate(): void {
super.onCreate();
}
}

View File

@ -0,0 +1,73 @@
/*
* Copyright (c) 2023-2025 Haitai FangYuan Co., Ltd.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import window from '@ohos.window';
import Want from '@ohos.app.ability.Want';
import AbilityConstant from '@ohos.app.ability.AbilityConstant';
import { Configuration } from '@ohos.app.ability.Configuration';
import { WebAbility } from 'web_engine';
export default class BrowserAbility extends WebAbility {
onConfigurationUpdate(config: Configuration) {
super.onConfigurationUpdate(config);
}
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) {
super.onCreate(want, launchParam);
}
async onPrepareToTerminateAsync(): Promise<boolean> {
return await super.onPrepareToTerminateAsync();
}
async onDestroy(): Promise<void> {
await super.onDestroy();
}
onWindowStageCreate(windowStage: window.WindowStage) {
super.onWindowStageCreate(windowStage);
}
onWindowStageDestroy() {
super.onWindowStageDestroy();
}
onForeground() {
super.onForeground();
}
onBackground() {
super.onBackground();
}
override getContentPath(): string {
return 'pages/WindowNode';
}
};

View File

@ -0,0 +1,69 @@
/*
* Copyright (c) 2023-2025 Haitai FangYuan Co., Ltd.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import window from '@ohos.window';
import Want from '@ohos.app.ability.Want';
import AbilityConstant from '@ohos.app.ability.AbilityConstant';
import { Configuration } from '@ohos.app.ability.Configuration';
import { WebAbility } from 'web_engine';
export default class EntryAbility extends WebAbility {
onConfigurationUpdate(config: Configuration) {
super.onConfigurationUpdate(config);
}
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) {
super.onCreate(want, launchParam);
}
async onPrepareToTerminateAsync(): Promise<boolean> {
return await super.onPrepareToTerminateAsync();
}
async onDestroy(): Promise<void> {
await super.onDestroy();
}
onWindowStageCreate(windowStage: window.WindowStage) {
super.onWindowStageCreate(windowStage);
}
onWindowStageDestroy() {
super.onWindowStageDestroy();
}
onForeground() {
super.onForeground();
}
onBackground() {
super.onBackground();
}
};

View File

@ -0,0 +1,78 @@
/*
* Copyright (c) 2023-2025 Haitai FangYuan Co., Ltd.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import AbilityConstant from '@ohos.app.ability.AbilityConstant';
import { Configuration } from '@ohos.app.ability.Configuration';
import window from '@ohos.window';
import Want from '@ohos.app.ability.Want';
import { deviceInfo } from '@kit.BasicServicesKit';
import { WebAbility } from 'web_engine';;
export default class StatelessAbility extends WebAbility {
onConfigurationUpdate(config: Configuration) {
super.onConfigurationUpdate(config);
}
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) {
super.onCreate(want, launchParam);
}
async onPrepareToTerminateAsync(): Promise<boolean> {
return await super.onPrepareToTerminateAsync();
}
async onDestroy(): Promise<void> {
await super.onDestroy();
}
onWindowStageCreate(windowStage: window.WindowStage) {
super.onWindowStageCreate(windowStage);
if (deviceInfo.sdkApiVersion >= 14) {
windowStage.setWindowRectAutoSave(false);
}
}
onWindowStageDestroy() {
super.onWindowStageDestroy();
}
onForeground() {
super.onForeground();
}
onBackground() {
super.onBackground();
}
override getContentPath(): string {
return 'pages/Index';
}
};

View File

@ -0,0 +1,58 @@
/*
* Copyright (c) 2023-2025 Haitai FangYuan Co., Ltd.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import Want from '@ohos.app.ability.Want';
import { WebEmbeddedAbility } from 'web_engine';
import { AbilityConstant, UIExtensionContentSession } from '@kit.AbilityKit';
export default class BrowserEmbeddedAbility extends WebEmbeddedAbility {
onCreate(launchParam: AbilityConstant.LaunchParam) {
super.onCreate(launchParam)
}
onForeground() {
super.onForeground()
}
onBackground() {
super.onBackground()
}
onDestroy() {
super.onDestroy()
}
onSessionCreate(want: Want, session: UIExtensionContentSession) {
super.onSessionCreate(want, session)
}
onSessionDestroy(session: UIExtensionContentSession) {
super.onSessionDestroy(session)
}
};

View File

@ -0,0 +1,50 @@
/*
* Copyright (c) 2023-2025 Haitai FangYuan Co., Ltd.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import { WebEmbeddedWindow } from 'web_engine';
import { KeyCode } from '@kit.InputKit';
let storage = LocalStorage.getShared();
@Entry(storage)
@Component
struct EmbeddedWindow {
build() {
Row() {
WebEmbeddedWindow()
}.onKeyEvent((event?: KeyEvent) => {
if (event) {
if (event.type == KeyType.Down && event.keyCode == KeyCode.KEYCODE_ESCAPE) {
event.stopPropagation();
}
}
})
.width('100%')
.height('100%')
}
}

View File

@ -0,0 +1,52 @@
/*
* Copyright (c) 2023-2025 Haitai FangYuan Co., Ltd.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import { WebWindow } from 'web_engine';
import CustomChildProcess from '../process/CustomChildProcess';
import { KeyCode } from '@kit.InputKit';
CustomChildProcess.toString();
let storage = LocalStorage.getShared();
@Entry(storage)
@Component
struct Index {
build() {
Row() {
WebWindow()
}.onKeyEvent((event?: KeyEvent) => {
if (event) {
if (event.type == KeyType.Down && event.keyCode == KeyCode.KEYCODE_ESCAPE) {
event.stopPropagation();
}
}
})
.width('100%')
.height('100%')
}
}

View File

@ -0,0 +1,43 @@
/*
* Copyright (c) 2023-2025 Haitai FangYuan Co., Ltd.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import { WebSubWindow } from 'web_engine';
let subStorage = LocalStorage.getShared();
@Entry(subStorage)
@Component
struct SubWindow {
build() {
Column() {
WebSubWindow()
}
.width('100%')
.height('100%')
}
}

View File

@ -0,0 +1,50 @@
/*
* Copyright (c) 2023-2025 Haitai FangYuan Co., Ltd.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import { WebWindowNode } from 'web_engine';
import { KeyCode } from '@kit.InputKit';
let storage = LocalStorage.getShared();
@Entry(storage)
@Component
struct WindowNode {
build() {
Row() {
WebWindowNode()
}.onKeyEvent((event?: KeyEvent) => {
if (event) {
if (event.type == KeyType.Down && event.keyCode == KeyCode.KEYCODE_ESCAPE) {
event.stopPropagation();
}
}
})
.width('100%')
.height('100%')
}
}

View File

@ -0,0 +1,40 @@
/*
* Copyright (c) 2023-2025 Haitai FangYuan Co., Ltd.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import { WebChildProcess } from 'web_engine/childProcess';
export default class CustomChildProcess extends WebChildProcess {
onStart(): void {
super.onStart();
}
static toString(): string {
return "CustomChildProcess";
}
}

119
chromium/src/main/module.json5 Executable file
View File

@ -0,0 +1,119 @@
{
"module": {
"name": "chromium",
"type": "entry",
"srcEntry": "./ets/Application/AbilityStage.ets",
"description": "$string:module_desc",
"mainElement": "EntryAbility",
"deviceTypes": [
"2in1"
],
"deliveryWithInstall": true,
"installationFree": false,
"pages": "$profile:main_pages",
"abilities": [
{
"name": "EntryAbility",
"srcEntry": "./ets/entryability/EntryAbility.ets",
"description": "$string:EntryAbility_desc",
"icon": "$media:app_icon",
"label": "$string:EntryAbility_label",
"startWindowIcon": "$media:app_icon",
"startWindowBackground": "$color:start_window_background",
"launchType": "specified",
"removeMissionAfterTerminate": true,
"exported": true,
"skills": [
{
"entities": [
"entity.system.home",
"entity.system.browsable"
],
"actions": [
"action.system.home",
"ohos.want.action.viewData"
],
"uris": [
{
"type": "application/pdf",
"scheme": 'file'
},
{
"type": "text/html",
"scheme": 'file'
},
{
"type": "application/x-mimearchive",
"scheme": 'file'
},
{
"scheme": "http"
},
{
"scheme": "https"
}
]
}
],
"process": ':browser'
},
{
"name": "BrowserAbility",
"srcEntry": "./ets/entryability/BrowserAbility.ets",
"description": "$string:BrowserAbility_desc",
"startWindowIcon": "$media:app_icon",
"startWindowBackground": "$color:start_window_background",
"removeMissionAfterTerminate": true,
"exported": true,
"skills": [
{
"actions": [
"ohos.want.action.viewData"
],
"uris": [
{
"type": "application/pdf",
"scheme": 'file'
},
{
"type": "text/html",
"scheme": 'file'
},
{
"type": "application/x-mimearchive",
"scheme": 'file'
},
{
"scheme": "http"
},
{
"scheme": "https"
}
]
}
],
"process": ':browser'
},
{
"name": "StatelessAbility",
"srcEntry": "./ets/entryability/StatelessAbility.ets",
"description": "$string:StatelessAbility_desc",
"label": "$string:StatelessAbility_label",
"startWindowIcon": "$media:app_icon",
"startWindowBackground": "$color:start_window_background",
"launchType": "specified",
"removeMissionAfterTerminate": true,
"exported": true,
"process": ':browser'
}
],
"extensionAbilities": [
{
"name": "BrowserEmbeddedAbility",
"srcEntry": "./ets/extensionAbility/BrowserEmbeddedAbility.ets",
"type": "embeddedUI",
"process": ':browser'
}
]
}
}

View File

@ -0,0 +1,8 @@
{
"color": [
{
"name": "start_window_background",
"value": "#FFFFFF"
}
]
}

View File

@ -0,0 +1,32 @@
{
"string": [
{
"name": "module_desc",
"value": "module description"
},
{
"name": "EntryAbility_desc",
"value": "description"
},
{
"name": "EntryAbility_label",
"value": "Chromium"
},
{
"name": "BrowserAbility_desc",
"value": "description"
},
{
"name": "BrowserAbility_label",
"value": "BrowserAbility"
},
{
"name": "StatelessAbility_desc",
"value": "description"
},
{
"name": "StatelessAbility_label",
"value": "StatelessAbility"
}
]
}

View File

@ -0,0 +1,8 @@
{
"src": [
"pages/Index",
"pages/SubWindow",
"pages/EmbeddedWindow",
"pages/WindowNode"
]
}

View File

@ -0,0 +1,16 @@
{
"string": [
{
"name": "module_desc",
"value": "module description"
},
{
"name": "EntryAbility_desc",
"value": "description"
},
{
"name": "EntryAbility_label",
"value": "Chromium"
}
]
}

View File

@ -0,0 +1,16 @@
{
"string": [
{
"name": "module_desc",
"value": "模块描述"
},
{
"name": "EntryAbility_desc",
"value": "description"
},
{
"name": "EntryAbility_label",
"value": "Chromium"
}
]
}

View File

@ -0,0 +1,35 @@
import hilog from '@ohos.hilog';
import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium';
export default function abilityTest() {
describe('ActsAbilityTest', () => {
// Defines a test suite. Two parameters are supported: test suite name and test suite function.
beforeAll(() => {
// Presets an action, which is performed only once before all test cases of the test suite start.
// This API supports only one parameter: preset action function.
})
beforeEach(() => {
// Presets an action, which is performed before each unit test case starts.
// The number of execution times is the same as the number of test cases defined by **it**.
// This API supports only one parameter: preset action function.
})
afterEach(() => {
// Presets a clear action, which is performed after each unit test case ends.
// The number of execution times is the same as the number of test cases defined by **it**.
// This API supports only one parameter: clear action function.
})
afterAll(() => {
// Presets a clear action, which is performed after all test cases of the test suite end.
// This API supports only one parameter: clear action function.
})
it('assertContain', 0, () => {
// Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function.
hilog.info(0x0000, 'testTag', '%{public}s', 'it begin');
let a = 'abc';
let b = 'b';
// Defines a variety of assertion methods, which are used to declare expected boolean conditions.
expect(a).assertContain(b);
expect(a).assertEqual(a);
})
})
}

View File

@ -0,0 +1,5 @@
import abilityTest from './Ability.test';
export default function testsuite() {
abilityTest();
}

View File

@ -0,0 +1,50 @@
import UIAbility from '@ohos.app.ability.UIAbility';
import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry';
import hilog from '@ohos.hilog';
import { Hypium } from '@ohos/hypium';
import testsuite from '../test/List.test';
import window from '@ohos.window';
import Want from '@ohos.app.ability.Want';
import AbilityConstant from '@ohos.app.ability.AbilityConstant';
export default class TestAbility extends UIAbility {
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) {
hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onCreate');
hilog.info(0x0000, 'testTag', '%{public}s', 'want param:' + JSON.stringify(want) ?? '');
hilog.info(0x0000, 'testTag', '%{public}s', 'launchParam:' + JSON.stringify(launchParam) ?? '');
let abilityDelegator: AbilityDelegatorRegistry.AbilityDelegator;
abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator();
let abilityDelegatorArguments: AbilityDelegatorRegistry.AbilityDelegatorArgs;
abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments();
hilog.info(0x0000, 'testTag', '%{public}s', 'start run testcase!!!');
Hypium.hypiumTest(abilityDelegator, abilityDelegatorArguments, testsuite);
}
onDestroy() {
hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onDestroy');
}
onWindowStageCreate(windowStage: window.WindowStage) {
hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onWindowStageCreate');
windowStage.loadContent('testability/pages/Index', (err, data) => {
if (err.code) {
hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
return;
}
hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s',
JSON.stringify(data) ?? '');
});
}
onWindowStageDestroy() {
hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onWindowStageDestroy');
}
onForeground() {
hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onForeground');
}
onBackground() {
hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onBackground');
}
}

View File

@ -0,0 +1,17 @@
@Entry
@Component
struct Index {
@State message: string = 'Hello World';
build() {
Row() {
Column() {
Text(this.message)
.fontSize(50)
.fontWeight(FontWeight.Bold)
}
.width('100%')
}
.height('100%')
}
}

View File

@ -0,0 +1,47 @@
import hilog from '@ohos.hilog';
import TestRunner from '@ohos.application.testRunner';
import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry';
import Want from '@ohos.app.ability.Want';
let abilityDelegator: AbilityDelegatorRegistry.AbilityDelegator | undefined = undefined
let abilityDelegatorArguments: AbilityDelegatorRegistry.AbilityDelegatorArgs | undefined = undefined
async function onAbilityCreateCallback() {
hilog.info(0x0000, 'testTag', '%{public}s', 'onAbilityCreateCallback');
}
async function addAbilityMonitorCallback(err : Error) {
hilog.info(0x0000, 'testTag', 'addAbilityMonitorCallback : %{public}s', JSON.stringify(err) ?? '');
}
export default class OpenHarmonyTestRunner implements TestRunner {
constructor() {
}
onPrepare() {
hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner OnPrepare ');
}
async onRun() {
hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner onRun run');
abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments()
abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator()
const bundleName = abilityDelegatorArguments.bundleName;
const testAbilityName = 'TestAbility';
let lMonitor: AbilityDelegatorRegistry.AbilityMonitor = {
abilityName: testAbilityName,
onAbilityCreate: onAbilityCreateCallback,
};
abilityDelegator.addAbilityMonitor(lMonitor, addAbilityMonitorCallback)
const want: Want = {
bundleName: bundleName,
abilityName: testAbilityName
};
abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator();
abilityDelegator.startAbility(want, (err, data) => {
hilog.info(0x0000, 'testTag', 'startAbility : err : %{public}s', JSON.stringify(err) ?? '');
hilog.info(0x0000, 'testTag', 'startAbility : data : %{public}s',JSON.stringify(data) ?? '');
})
hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner onRun end');
}
}

View File

@ -0,0 +1,36 @@
{
"module": {
"name": "pc_test",
"type": "feature",
"description": "$string:module_test_desc",
"mainElement": "TestAbility",
"deviceTypes": [
"2in1"
],
"deliveryWithInstall": true,
"installationFree": false,
"pages": "$profile:test_pages",
"abilities": [
{
"name": "TestAbility",
"srcEntry": "./ets/testability/TestAbility.ets",
"description": "$string:TestAbility_desc",
"icon": "$media:icon",
"label": "$string:TestAbility_label",
"exported": true,
"startWindowIcon": "$media:icon",
"startWindowBackground": "$color:start_window_background",
"skills": [
{
"actions": [
"action.system.home"
],
"entities": [
"entity.system.home"
]
}
]
}
]
}
}

View File

@ -0,0 +1,8 @@
{
"color": [
{
"name": "start_window_background",
"value": "#FFFFFF"
}
]
}

View File

@ -0,0 +1,16 @@
{
"string": [
{
"name": "module_test_desc",
"value": "test ability description"
},
{
"name": "TestAbility_desc",
"value": "the test ability"
},
{
"name": "TestAbility_label",
"value": "test label"
}
]
}

View File

@ -0,0 +1,5 @@
{
"src": [
"testability/pages/Index"
]
}

View File

@ -0,0 +1,5 @@
import localUnitTest from './LocalUnit.test';
export default function testsuite() {
localUnitTest();
}

View File

@ -0,0 +1,33 @@
import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium';
export default function localUnitTest() {
describe('localUnitTest',() => {
// Defines a test suite. Two parameters are supported: test suite name and test suite function.
beforeAll(() => {
// Presets an action, which is performed only once before all test cases of the test suite start.
// This API supports only one parameter: preset action function.
});
beforeEach(() => {
// Presets an action, which is performed before each unit test case starts.
// The number of execution times is the same as the number of test cases defined by **it**.
// This API supports only one parameter: preset action function.
});
afterEach(() => {
// Presets a clear action, which is performed after each unit test case ends.
// The number of execution times is the same as the number of test cases defined by **it**.
// This API supports only one parameter: clear action function.
});
afterAll(() => {
// Presets a clear action, which is performed after all test cases of the test suite end.
// This API supports only one parameter: clear action function.
});
it('assertContain', 0, () => {
// Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function.
let a = 'abc';
let b = 'b';
// Defines a variety of assertion methods, which are used to declare expected boolean conditions.
expect(a).assertContain(b);
expect(a).assertEqual(a);
});
});
}

30
electron/build-profile.json5 Executable file
View File

@ -0,0 +1,30 @@
{
"apiType": "stageMode",
"buildOption": {
"arkOptions": {
},
},
"buildOptionSet": [
{
"name": "release",
"arkOptions": {
"obfuscation": {
"ruleOptions": {
"enable": true,
"files": [
"./obfuscation-rules.txt"
]
}
}
}
},
],
"targets": [
{
"name": "default"
},
{
"name": "ohosTest",
}
]
}

6
electron/hvigorfile.ts Executable file
View File

@ -0,0 +1,6 @@
import { hapTasks } from '@ohos/hvigor-ohos-plugin';
export default {
system: hapTasks, /* Built-in plugin of Hvigor. It cannot be modified. */
plugins:[] /* Custom plugin to extend the functionality of Hvigor. */
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

18
electron/obfuscation-rules.txt Executable file
View File

@ -0,0 +1,18 @@
# Define project specific obfuscation rules here.
# You can include the obfuscation configuration files in the current module's build-profile.json5.
#
# For more details, see
# https://gitee.com/openharmony/arkcompiler_ets_frontend/blob/master/arkguard/README.md
# Obfuscation options:
# -disable-obfuscation: disable all obfuscations
# -enable-property-obfuscation: obfuscate the property names
# -enable-toplevel-obfuscation: obfuscate the names in the global scope
# -compact: remove unnecessary blank spaces and all line feeds
# -remove-log: remove all console.* statements
# -print-namecache: print the name cache that contains the mapping from the old names to new names
# -apply-namecache: reuse the given cache file
# Keep options:
# -keep-property-name: specifies property names that you want to keep
# -keep-global-name: specifies names that you want to keep in the global scope

View File

@ -0,0 +1,48 @@
{
"meta": {
"stableOrder": true,
"enableUnifiedLockfile": false
},
"lockfileVersion": 3,
"ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.",
"specifiers": {
"inversify@^6.0.1": "inversify@6.0.1",
"libadapter.so@../web_engine/src/main/cpp/types/libadapter": "libadapter.so@../web_engine/src/main/cpp/types/libadapter",
"reflect-metadata@^0.1.13": "reflect-metadata@0.2.1",
"web_engine@../web_engine": "web_engine@../web_engine"
},
"packages": {
"inversify@6.0.1": {
"name": "inversify",
"version": "6.0.1",
"integrity": "sha512-B3ex30927698TJENHR++8FfEaJGqoWOgI6ZY5Ht/nLUsFCwHn6akbwtnUAPCgUepAnTpe2qHxhDNjoKLyz6rgQ==",
"resolved": "https://ohpm.openharmony.cn/ohpm/inversify/-/inversify-6.0.1.tgz",
"shasum": "b20d35425d5d8c5cd156120237aad0008d969f02",
"registryType": "ohpm"
},
"libadapter.so@../web_engine/src/main/cpp/types/libadapter": {
"name": "libadapter.so",
"version": "0.0.0",
"resolved": "../web_engine/src/main/cpp/types/libadapter",
"registryType": "local"
},
"reflect-metadata@0.2.1": {
"name": "reflect-metadata",
"version": "0.2.1",
"integrity": "sha512-i5lLI6iw9AU3Uu4szRNPPEkomnkjRTaVt9hy/bn5g/oSzekBSMeLZblcjP74AW0vBabqERLLIrz+gR8QYR54Tw==",
"resolved": "https://ohpm.openharmony.cn/ohpm/reflect-metadata/-/reflect-metadata-0.2.1.tgz",
"shasum": "8d5513c0f5ef2b4b9c3865287f3c0940c1f67f74",
"registryType": "ohpm"
},
"web_engine@../web_engine": {
"name": "web_engine",
"version": "1.0.0",
"resolved": "../web_engine",
"registryType": "local",
"dependencies": {
"inversify": "^6.0.1",
"reflect-metadata": "^0.1.13"
}
}
}
}

12
electron/oh-package.json5 Executable file
View File

@ -0,0 +1,12 @@
{
"license": "",
"devDependencies": {},
"author": "",
"name": "electron",
"description": "Please describe the basic information.",
"main": "",
"version": "1.0.0",
"dependencies": {
"web_engine": 'file:../web_engine',
}
}

View File

@ -0,0 +1,36 @@
/*
* Copyright (c) 2023-2025 Haitai FangYuan Co., Ltd.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import { WebAbilityStage } from 'web_engine';
export default class MyAbilityStage extends WebAbilityStage {
onCreate(): void {
super.onCreate();
}
}

View File

@ -0,0 +1,69 @@
/*
* Copyright (c) 2023-2025 Haitai FangYuan Co., Ltd.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import window from '@ohos.window';
import Want from '@ohos.app.ability.Want';
import AbilityConstant from '@ohos.app.ability.AbilityConstant';
import { Configuration } from '@ohos.app.ability.Configuration';
import { WebAbility } from 'web_engine';
export default class BrowserAbility extends WebAbility {
onConfigurationUpdate(config: Configuration) {
super.onConfigurationUpdate(config);
}
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) {
super.onCreate(want, launchParam);
}
onDestroy() {
super.onDestroy();
}
onWindowStageCreate(windowStage: window.WindowStage) {
super.onWindowStageCreate(windowStage);
}
onWindowStageDestroy() {
super.onWindowStageDestroy();
}
onForeground() {
super.onForeground();
}
onBackground() {
super.onBackground();
}
override getContentPath(): string {
return 'pages/WindowNode';
}
};

View File

@ -0,0 +1,65 @@
/*
* Copyright (c) 2023-2025 Haitai FangYuan Co., Ltd.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import window from '@ohos.window';
import Want from '@ohos.app.ability.Want';
import AbilityConstant from '@ohos.app.ability.AbilityConstant';
import { Configuration } from '@ohos.app.ability.Configuration';
import { WebAbility } from 'web_engine';
export default class EntryAbility extends WebAbility {
onConfigurationUpdate(config: Configuration) {
super.onConfigurationUpdate(config);
}
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) {
super.onCreate(want, launchParam);
}
onDestroy() {
super.onDestroy();
}
onWindowStageCreate(windowStage: window.WindowStage) {
super.onWindowStageCreate(windowStage);
}
onWindowStageDestroy() {
super.onWindowStageDestroy();
}
onForeground() {
super.onForeground();
}
onBackground() {
super.onBackground();
}
};

View File

@ -0,0 +1,74 @@
/*
* Copyright (c) 2023-2025 Haitai FangYuan Co., Ltd.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import AbilityConstant from '@ohos.app.ability.AbilityConstant';
import { Configuration } from '@ohos.app.ability.Configuration';
import window from '@ohos.window';
import Want from '@ohos.app.ability.Want';
import { deviceInfo } from '@kit.BasicServicesKit';
import { WebAbility } from 'web_engine';;
export default class StatelessAbility extends WebAbility {
onConfigurationUpdate(config: Configuration) {
super.onConfigurationUpdate(config);
}
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) {
super.onCreate(want, launchParam);
}
onDestroy() {
super.onDestroy();
}
onWindowStageCreate(windowStage: window.WindowStage) {
super.onWindowStageCreate(windowStage);
if (deviceInfo.sdkApiVersion >= 14) {
windowStage.setWindowRectAutoSave(false);
}
}
onWindowStageDestroy() {
super.onWindowStageDestroy();
}
onForeground() {
super.onForeground();
}
onBackground() {
super.onBackground();
}
override getContentPath(): string {
return 'pages/Index';
}
};

View File

@ -0,0 +1,60 @@
/*
* Copyright (c) 2023-2025 Haitai FangYuan Co., Ltd.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import { StatusBarViewExtensionAbility } from '@kit.StatusBarExtensionKit';
import { UIExtensionContentSession, Want } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
let TAG = 'StatusBarEntryAbility';
export default class StatusBarEntryAbility extends StatusBarViewExtensionAbility {
onCreate() {
hilog.info(0x0000, TAG, '%{public}s', 'Ability onCreate');
}
onSessionCreate(want: Want, session: UIExtensionContentSession) {
hilog.info(0x0000, TAG, '%{public}s', 'Ability onSessionCreate');
session.loadContent('pages/StatusBarPage');
}
onForeground() {
hilog.info(0x0000, TAG, '%{public}s', 'Ability onForeground');
}
onBackground() {
hilog.info(0x0000, TAG, '%{public}s', 'Ability onBackground');
}
onSessionDestroy(session: UIExtensionContentSession) {
hilog.info(0x0000, TAG, '%{public}s', 'Ability onSessionDestroy');
}
onDestroy() {
hilog.info(0x0000, TAG, '%{public}s', 'Ability onDestroy');
}
}

View File

@ -0,0 +1,58 @@
/*
* Copyright (c) 2023-2025 Haitai FangYuan Co., Ltd.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import Want from '@ohos.app.ability.Want';
import { WebEmbeddedAbility } from 'web_engine';
import { AbilityConstant, UIExtensionContentSession } from '@kit.AbilityKit';
export default class BrowserEmbeddedAbility extends WebEmbeddedAbility {
onCreate(launchParam: AbilityConstant.LaunchParam) {
super.onCreate(launchParam)
}
onForeground() {
super.onForeground()
}
onBackground() {
super.onBackground()
}
onDestroy() {
super.onDestroy()
}
onSessionCreate(want: Want, session: UIExtensionContentSession) {
super.onSessionCreate(want, session)
}
onSessionDestroy(session: UIExtensionContentSession) {
super.onSessionDestroy(session)
}
};

View File

@ -0,0 +1,50 @@
/*
* Copyright (c) 2023-2025 Haitai FangYuan Co., Ltd.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import { WebEmbeddedWindow } from 'web_engine';
import { KeyCode } from '@kit.InputKit';
let storage = LocalStorage.getShared();
@Entry(storage)
@Component
struct EmbeddedWindow {
build() {
Row() {
WebEmbeddedWindow()
}.onKeyEvent((event?: KeyEvent) => {
if (event) {
if (event.type == KeyType.Down && event.keyCode == KeyCode.KEYCODE_ESCAPE) {
event.stopPropagation();
}
}
})
.width('100%')
.height('100%')
}
}

View File

@ -0,0 +1,91 @@
/*
* Copyright (c) 2023-2025 Haitai FangYuan Co., Ltd.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import { WebWindow } from 'web_engine';
import { KeyCode } from '@kit.InputKit';
import CustomChildProcess from '../process/CustomChildProcess';
interface IStyleData {
backgroundColor: string,
opacity: number
};
interface IUpdateStyle {
registerUpdateStyleFunction: Function,
removeUpdateStyleFunction: Function
};
CustomChildProcess.toString();
let storage = LocalStorage.getShared();
@Entry(storage)
@Component
struct Index {
@LocalStorageLink('updateStyle') updateStyle: IUpdateStyle = {
registerUpdateStyleFunction: (id: string, initStyle: IStyleData, func: (style: IStyleData) => void) => {},
removeUpdateStyleFunction: (id: string) => {}
};
@LocalStorageLink('xcomponentId') xcomponentId: string = '';
private initStyle: IStyleData = {
backgroundColor: 'ffffffff',
opacity: 1
};
@State private backgroundColor_: string = `#${this.initStyle.backgroundColor}`;
@State private opacity_: number = this.initStyle.opacity;
aboutToAppear() {
// registerUpdateStyleFunction
this.updateStyle.registerUpdateStyleFunction(this.xcomponentId, this.initStyle, (style: IStyleData) => {
this.backgroundColor_ = `#${style.backgroundColor}`;
this.opacity_ = style.opacity;
});
}
aboutToDisappear() {
// removeUpdateStyleFunction
this.updateStyle.removeUpdateStyleFunction(this.xcomponentId);
}
build() {
Row() {
WebWindow()
}.onKeyEvent((event?: KeyEvent) => {
if (event) {
if (event.type == KeyType.Down && event.keyCode == KeyCode.KEYCODE_ESCAPE) {
event.stopPropagation();
}
}
})
.backgroundColor(this.backgroundColor_)
.opacity(this.opacity_)
.width('100%')
.height('100%')
}
}

View File

@ -0,0 +1,60 @@
/*
* Copyright (c) 2023-2025 Haitai FangYuan Co., Ltd.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import { ILoginInfo, ILogin } from 'web_engine';
import { QuickLoginButtonComponent } from './QuickLoginButtonComponent'
let storage = LocalStorage.getShared();
@Entry(storage)
@Component
struct Index {
@LocalStorageLink('login') login: ILogin = {
loginCallbackFunc: (loginInfo: ILoginInfo) => {}
};
private loginCallback_: (loginInfo: ILoginInfo) => void = (loginInfo: ILoginInfo) => {};
aboutToAppear() {
this.loginCallback_ = this.login.loginCallbackFunc;
}
aboutToDisappear() {
}
build() {
RelativeContainer() {
QuickLoginButtonComponent({ loginCallback: this.loginCallback_ })
.backgroundColor(0xffffff)
}
.height('100%')
.width('100%')
}
}

View File

@ -0,0 +1,639 @@
import { loginComponentManager, LoginWithHuaweiIDButton } from '@kit.AccountKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { promptAction, router } from '@kit.ArkUI';
import { connection } from '@kit.NetworkKit';
import { authentication } from '@kit.AccountKit';
import { util } from '@kit.ArkTS';
import { WebPage } from './WebPage'
import { ILoginInfo } from 'web_engine';
const loginFailInfo: ILoginInfo = {
status: false,
authCode: '',
unionId: '',
openId: '',
idToken: '',
anonymousPhone: ''
};
@Component
export struct QuickLoginButtonComponent {
// 获取登录信息的回调函数
loginCallback: (loginInfo: ILoginInfo) => void = (loginInfo: ILoginInfo) => {};
logTag: string = 'QuickLoginButtonComponent';
domainId: number = 0x0000;
// 第二步获取的匿名化手机号传到此处
@State quickLoginAnonymousPhone: string = 'not get anonymousPhone';
// 是否勾选协议
@State isSelected: boolean = false;
// 华为账号用户认证协议链接,此处仅为示例,实际开发过程中,出于可维护性、安全性等方面考虑,域名不建议硬编码在本地
private static USER_AUTHENTICATION_PROTOCOL: string =
'https://privacy.consumer.huawei.com/legal/id/authentication-terms.htm?code=CN&language=zh-CN';
private static USER_SERVICE_TAG = '用户服务协议';
private static PRIVACY_TAG = '隐私协议';
private static USER_AUTHENTICATION_TAG = '华为账号用户认证协议';
// 定义LoginWithHuaweiIDButton展示的隐私文本展示应用的用户服务协议、隐私协议和华为账号用户认证协议
privacyText: loginComponentManager.PrivacyText[] = [{
text: '已阅读并同意',
type: loginComponentManager.TextType.PLAIN_TEXT
}, {
text: '《用户服务协议》',
tag: QuickLoginButtonComponent.USER_SERVICE_TAG,
type: loginComponentManager.TextType.RICH_TEXT
}, {
text: '《隐私协议》',
tag: QuickLoginButtonComponent.PRIVACY_TAG,
type: loginComponentManager.TextType.RICH_TEXT
}, {
text: '和',
type: loginComponentManager.TextType.PLAIN_TEXT
}, {
text: '《华为账号用户认证协议》',
tag: QuickLoginButtonComponent.USER_AUTHENTICATION_TAG,
type: loginComponentManager.TextType.RICH_TEXT
}, {
text: '。',
type: loginComponentManager.TextType.PLAIN_TEXT
}];
// 构造LoginWithHuaweiIDButton组件的控制器
controller: loginComponentManager.LoginWithHuaweiIDButtonController =
new loginComponentManager.LoginWithHuaweiIDButtonController()
/**
* 当应用使用自定义的登录页时如果用户未同意协议需要设置协议状态为NOT_ACCEPTED当用户同意协议后再设置
* 协议状态为ACCEPTED才可以使用华为账号一键登录功能
*/
.setAgreementStatus(loginComponentManager.AgreementStatus.NOT_ACCEPTED)
.onClickLoginWithHuaweiIDButton((error: BusinessError | undefined,
response: loginComponentManager.HuaweiIDCredential) => {
this.handleLoginWithHuaweiIDButton(error, response);
})
.onClickEvent((error: BusinessError, clickEvent: loginComponentManager.ClickEvent) => {
if (error) {
this.dealAllError(error);
return;
}
hilog.info(this.domainId, this.logTag, `onClickEvent clickEvent: ${clickEvent}`);
});
agreementDialog: CustomDialogController = new CustomDialogController({
builder: AgreementDialog({
privacyText: this.privacyText,
cancel: () => {
this.agreementDialog.close();
this.controller.setAgreementStatus(loginComponentManager.AgreementStatus.NOT_ACCEPTED);
},
confirm: () => {
this.agreementDialog.close();
this.isSelected = true;
this.controller.setAgreementStatus(loginComponentManager.AgreementStatus.ACCEPTED);
// 调用此方法,同意协议与登录一并完成,无需再次点击登录按钮
this.controller.continueLogin((error: BusinessError) => {
if (error) {
hilog.error(this.domainId, this.logTag,
`Failed to login with agreementDialog. errCode is ${error.code}, errMessage is ${error.message}`);
} else {
hilog.info(this.domainId, this.logTag,
'Succeeded in clicking agreementDialog continueLogin.');
}
});
},
clickHyperlinkText: () => {
this.agreementDialog.close();
this.jumpToPrivacyWebView();
}
}),
autoCancel: false,
alignment: DialogAlignment.Center,
});
// 传递页面渲染所需的数据,如匿名手机号等
aboutToAppear(): void {
this.getQuickLoginAnonymousPhone();
}
getQuickLoginAnonymousPhone() {
// 创建授权请求,并设置参数
const authRequest = new authentication.HuaweiIDProvider().createAuthorizationWithHuaweiIDRequest();
// 获取匿名手机号需传quickLoginAnonymousPhone这个scope传参之前需要先申请“华为账号一键登录”权限
authRequest.scopes = ['quickLoginAnonymousPhone'];
// 用于防跨站点请求伪造
authRequest.state = util.generateRandomUUID();
// 一键登录场景该参数必须设置为false
authRequest.forceAuthorization = false;
const controller = new authentication.AuthenticationController();
try {
controller.executeRequest(authRequest).then((response: authentication.AuthorizationWithHuaweiIDResponse) => {
// 获取到UnionID、OpenID、匿名手机号
const unionID = response.data?.unionID;
const openID = response.data?.openID;
const anonymousPhone = response.data?.extraInfo?.quickLoginAnonymousPhone as string;
if (anonymousPhone) {
hilog.info(this.domainId, this.logTag, 'Succeeded in authentication.');
const quickLoginAnonymousPhone: string = anonymousPhone;
// 获取到手机号
this.quickLoginAnonymousPhone = quickLoginAnonymousPhone;
return;
}
hilog.info(this.domainId, this.logTag, 'Succeeded in authentication. AnonymousPhone is empty.');
// 未获取到匿名手机号需要跳转到应用自定义的登录页面
}).catch((error: BusinessError) => {
this.dealAllError(error);
})
} catch (error) {
this.dealAllError(error);
}
}
// Toast提示
showToast(resource: string) {
try {
promptAction.showToast({
message: resource,
duration: 2000
});
} catch (error) {
const message = (error as BusinessError).message
const code = (error as BusinessError).code
hilog.error(this.domainId, this.logTag, `showToast args errCode is ${code}, errMessage is ${message}`);
}
}
// 跳转华为账号用户认证协议页,该页面需在工程main_pages.json文件配置
jumpToPrivacyWebView() {
try {
// 需在module.json5中配置“ohos.permission.GET_NETWORK_INFO”权限
const checkNetConn = connection.hasDefaultNetSync();
if (!checkNetConn) {
this.showToast('服务或网络异常,请稍后重试');
return;
}
} catch (error) {
const message = error.message as string;
const code = error.code as string;
hilog.error(0x0000, 'testTag', `Failed to hasDefaultNetSync, errCode is ${code}, errMessage is ${message}`);
}
router.pushUrl({
// 需在module.json5配置“ohos.permission.INTERNET”网络权限
url: 'pages/WebPage',
params: {
isFromDialog: true,
url: QuickLoginButtonComponent.USER_AUTHENTICATION_PROTOCOL,
}
}, (err) => {
if (err) {
hilog.error(this.domainId, this.logTag,
`Failed to jumpToPrivacyWebView, errCode is ${err.code}, errMessage is ${err.message}`);
}
});
}
handleLoginWithHuaweiIDButton(error: BusinessError | undefined,
response: loginComponentManager.HuaweiIDCredential) {
if (error) {
hilog.error(this.domainId, this.logTag,
`Failed to login with LoginWithHuaweiIDButton. errCode is ${error.code}, errMessage is ${error.message}`);
if (error.code === ErrorCode.ERROR_CODE_NETWORK_ERROR) {
AlertDialog.show(
{
message: "网络未连接,请检查网络设置。",
offset: { dx: 0, dy: -12 },
alignment: DialogAlignment.Bottom,
autoCancel: false,
confirm: {
value: "知道了",
action: () => {
}
}
}
);
} else if (error.code === ErrorCode.ERROR_CODE_AGREEMENT_STATUS_NOT_ACCEPTED) {
// 未同意协议,弹出协议弹框,推荐使用该回调方式
this.agreementDialog.open();
} else if (error.code === ErrorCode.ERROR_CODE_LOGIN_OUT) {
// 华为账号未登录提示
this.showToast("华为账号未登录,请重试");
} else if (error.code === ErrorCode.ERROR_CODE_NOT_SUPPORTED) {
// 不支持该scopes或permissions提示
this.showToast("该scopes或permissions不支持");
} else if (error.code === ErrorCode.ERROR_CODE_PARAMETER_ERROR) {
// 参数错误提示
this.showToast("参数错误");
} else {
// 其他提示系统或服务异常
this.showToast('服务或网络异常,请稍后重试');
}
return;
}
try {
if (this.isSelected) {
if (response) {
hilog.info(this.domainId, this.logTag, 'Succeeded in clicking LoginWithHuaweiIDButton.');
// 开发者根据实际业务情况使用以下信息
const authCode = response.authorizationCode;
const openID = response.openID;
const unionID = response.unionID;
const idToken = response.idToken;
// 回传数据给 electron
const loginInfo: ILoginInfo = {
status: true,
authCode: authCode ? authCode.toString() : '',
unionId: unionID ? unionID.toString() : '',
openId: openID ? openID.toString() : '',
idToken: idToken ? idToken.toString() : '',
anonymousPhone: this.quickLoginAnonymousPhone.toString()
};
this.loginCallback(loginInfo);
}
} else {
this.agreementDialog.open();
}
} catch (err) {
hilog.error(this.domainId, this.logTag,
`Failed to login with LoginWithHuaweiIDButton, errCode: ${err.code}, errMessage: ${err.message}`);
AlertDialog.show(
{
message: '服务或网络异常,请稍后重试',
offset: { dx: 0, dy: -12 },
alignment: DialogAlignment.Bottom,
autoCancel: false,
confirm: {
value: '知道了',
action: () => {
}
}
}
);
}
}
// 错误处理
dealAllError(error: BusinessError): void {
hilog.error(this.domainId, this.logTag,
`Failed to login, errorCode is ${error.code}, errorMessage is ${error.message}`);
}
build() {
Scroll() {
Column() {
Column() {
Column() {
Button({ type: ButtonType.Normal }) {
Image($r('sys.media.ohos_ic_compnent_titlebar_back'))
.backgroundColor(Color.Transparent)
.borderRadius(20)
.width(24)
.height(24)
.draggable(false)
.autoResize(false)
.focusable(true)
.fillColor($r('sys.color.ohos_id_color_titlebar_icon'))
.matchTextDirection(true)
}
.alignSelf(ItemAlign.Start)
.backgroundColor($r('sys.color.ohos_id_color_button_normal'))
.borderRadius(20)
.width(40)
.height(40)
.onClick(() => {
// 手动关闭登录页面
this.loginCallback(loginFailInfo);
})
}.width('100%').margin({ top: 16, })
Column() {
Image($r('app.media.app_icon'))
.width(48)
.height(48)
.draggable(false)
.copyOption(CopyOptions.None)
.onComplete(() => {
hilog.info(this.domainId, this.logTag, 'appIcon loading success.');
})
.onError(() => {
hilog.error(this.domainId, this.logTag, 'appIcon loading fail.');
})
Text($r('app.string.app_name'))
.fontFamily($r('sys.string.ohos_id_text_font_family_medium'))
.fontWeight(FontWeight.Medium)
.fontWeight(FontWeight.Bold)
.maxFontSize($r('sys.float.ohos_id_text_size_headline8'))
.minFontSize($r('sys.float.ohos_id_text_size_body1'))
.maxLines(1)
.fontColor($r('sys.color.ohos_id_color_text_primary'))
.constraintSize({ maxWidth: '100%' })
.margin({
top: 12,
})
Text('应用描述')
.fontSize($r('sys.float.ohos_id_text_size_body2'))
.fontColor($r('sys.color.ohos_id_color_text_secondary'))
.fontFamily($r('sys.string.ohos_id_text_font_family_regular'))
.fontWeight(FontWeight.Regular)
.constraintSize({ maxWidth: '100%' })
.margin({
top: 8,
})
}.margin({
top: 10
})
Column() {
Text(this.quickLoginAnonymousPhone)
.fontSize(36)
.fontColor($r('sys.color.ohos_id_color_text_primary'))
.fontFamily($r('sys.string.ohos_id_text_font_family_medium'))
.fontWeight(FontWeight.Bold)
.lineHeight(48)
.textAlign(TextAlign.Center)
.maxLines(1)
.constraintSize({ maxWidth: '100%', minHeight: 48 })
Text('华为账号绑定号码')
.fontSize($r('sys.float.ohos_id_text_size_body2'))
.fontColor($r('sys.color.ohos_id_color_text_secondary'))
.fontFamily($r('sys.string.ohos_id_text_font_family_regular'))
.fontWeight(FontWeight.Regular)
.lineHeight(19)
.textAlign(TextAlign.Center)
.maxLines(1)
.constraintSize({ maxWidth: '100%' })
.margin({
top: 8
})
}.margin({
top: 64
})
Column() {
LoginWithHuaweiIDButton({
params: {
// LoginWithHuaweiIDButton支持的样式
style: loginComponentManager.Style.BUTTON_RED,
// 账号登录按钮在登录过程中展示加载态
extraStyle: {
buttonStyle: new loginComponentManager.ButtonStyle().loadingStyle({
show: true
})
},
// LoginWithHuaweiIDButton的边框圆角半径
borderRadius: 24,
// LoginWithHuaweiIDButton支持的登录类型
loginType: loginComponentManager.LoginType.QUICK_LOGIN,
// LoginWithHuaweiIDButton支持按钮的样式跟随系统深浅色模式切换
supportDarkMode: true,
// verifyPhoneNumber如果华为账号用户在过去90天内未进行短信验证是否拉起Account Kit提供的短信验证码页面
verifyPhoneNumber: true
},
controller: this.controller
})
}
.height(40)
.margin({
top: 56
})
Column() {
Button({
type: ButtonType.Capsule,
stateEffect: true
}) {
Text('其他方式登录')
.fontColor($r('sys.color.ohos_id_color_text_primary_activated'))
.fontFamily($r('sys.string.ohos_id_text_font_family_medium'))
.fontWeight(FontWeight.Medium)
.fontSize($r('sys.float.ohos_id_text_size_button1'))
.focusable(true)
.focusOnTouch(true)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.maxLines(1)
.padding({ left: 8, right: 8 })
}
.fontColor($r('sys.color.ohos_id_color_text_primary_activated'))
.fontFamily($r('sys.string.ohos_id_text_font_family_medium'))
.fontWeight(FontWeight.Medium)
.backgroundColor($r('sys.color.ohos_id_color_button_normal'))
.focusable(true)
.focusOnTouch(true)
.constraintSize({ minHeight: 40 })
.width('100%')
.onClick(() => {
// 跳转到应用自定义的登录页面
hilog.info(this.domainId, this.logTag, 'click optionalLoginButton.');
})
}.margin({ top: 16 })
}.width('100%')
Row() {
Row() {
Checkbox({ name: 'privacyCheckbox', group: 'privacyCheckboxGroup' })
.width(24)
.height(24)
.focusable(true)
.focusOnTouch(true)
.margin({ top: 0 })
.select(this.isSelected)
.onChange((value: boolean) => {
if (value) {
this.isSelected = true;
this.controller.setAgreementStatus(loginComponentManager.AgreementStatus.ACCEPTED);
} else {
this.isSelected = false;
this.controller.setAgreementStatus(loginComponentManager.AgreementStatus.NOT_ACCEPTED);
}
hilog.info(this.domainId, this.logTag, `agreementChecked: ${value}`);
})
}
Row() {
Text() {
ForEach(this.privacyText, (item: loginComponentManager.PrivacyText) => {
if (item?.type === loginComponentManager.TextType.PLAIN_TEXT && item?.text) {
Span(item?.text)
.fontColor($r('sys.color.ohos_id_color_text_secondary'))
.fontFamily($r('sys.string.ohos_id_text_font_family_regular'))
.fontWeight(FontWeight.Regular)
.fontSize($r('sys.float.ohos_id_text_size_body3'))
} else if (item?.type === loginComponentManager.TextType.RICH_TEXT && item?.text) {
Span(item?.text)
.fontColor($r('sys.color.ohos_id_color_text_primary_activated'))
.fontFamily($r('sys.string.ohos_id_text_font_family_medium'))
.fontWeight(FontWeight.Medium)
.fontSize($r('sys.float.ohos_id_text_size_body3'))
.focusable(true)
.focusOnTouch(true)
.onClick(() => {
// 应用需要根据item.tag实现协议页面的跳转逻辑
hilog.info(this.domainId, this.logTag, `click privacy text tag: ${item.tag}`);
// 华为账号用户认证协议
if (item.tag === QuickLoginButtonComponent.USER_AUTHENTICATION_TAG) {
this.jumpToPrivacyWebView();
}
})
}
}, (item: loginComponentManager.PrivacyText) => item.text.toString())
}
.width('100%')
}
.margin({ left: 12 })
.layoutWeight(1)
.constraintSize({ minHeight: 24 })
}
.alignItems(VerticalAlign.Top)
.margin({
top:16,
bottom: 16
})
}
.justifyContent(FlexAlign.SpaceBetween)
.constraintSize({ minHeight: '100%' })
.margin({
left: 16,
right: 16
})
}
.width('100%')
.height('100%')
}
}
@CustomDialog
export struct AgreementDialog {
logTag: string = 'AgreementDialog';
domainId: number = 0x0000;
dialogController?: CustomDialogController;
cancel: () => void = () => {
};
confirm: () => void = () => {
};
clickHyperlinkText: () => void = () => {
};
privacyText: loginComponentManager.PrivacyText[] = [];
private static USER_AUTHENTICATION_TAG = '华为账号用户认证协议';
build() {
Column() {
Row() {
Text('用户协议与隐私条款')
.id('loginPanel_agreement_dialog_privacy_title')
.maxFontSize($r('sys.float.ohos_id_text_size_headline8'))
.minFontSize($r('sys.float.ohos_id_text_size_body1'))
.fontColor($r('sys.color.ohos_id_color_text_primary'))
.fontFamily($r('sys.string.ohos_id_text_font_family_medium'))
.fontWeight(FontWeight.Bold)
.textAlign(TextAlign.Center)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.maxLines(2)
}
.alignItems(VerticalAlign.Center)
.constraintSize({ minHeight: 56, maxWidth: 400 })
.margin({
left: $r('sys.float.ohos_id_max_padding_start'),
right: $r('sys.float.ohos_id_max_padding_start')
})
Row() {
Text() {
ForEach(this.privacyText, (item: loginComponentManager.PrivacyText) => {
if (item?.type === loginComponentManager.TextType.PLAIN_TEXT && item?.text) {
Span(item?.text)
.fontSize($r('sys.float.ohos_id_text_size_body1'))
.fontColor($r('sys.color.ohos_id_color_text_primary'))
.fontFamily($r('sys.string.ohos_id_text_font_family_regular'))
.fontWeight(FontWeight.Regular)
} else if (item?.type === loginComponentManager.TextType.RICH_TEXT && item?.text) {
Span(item?.text)
.fontSize($r('sys.float.ohos_id_text_size_body1'))
.fontColor('#CE0E2D')
.fontFamily($r('sys.string.ohos_id_text_font_family_medium'))
.fontWeight(FontWeight.Medium)
.focusable(true)
.focusOnTouch(true)
.onClick(() => {
// 应用需要根据item.tag实现协议页面的跳转逻辑
hilog.info(this.domainId, this.logTag, `click privacy text tag: ${item.tag}`);
// 华为账号用户认证协议
if (item.tag === AgreementDialog.USER_AUTHENTICATION_TAG) {
hilog.info(this.domainId, this.logTag, 'AgreementDialog click.');
this.clickHyperlinkText();
}
})
}
}, (item: loginComponentManager.PrivacyText) => item.text.toString())
}
.width('100%')
.textOverflow({ overflow: TextOverflow.Ellipsis })
.maxLines(10)
.textAlign(TextAlign.Start)
.focusable(true)
.focusOnTouch(true)
.padding({ left: 24, right: 24 })
}.width('100%')
Flex({
direction: FlexDirection.Row
}) {
Button('取消',
{ type: ButtonType.Capsule, stateEffect: true })
.id('loginPanel_agreement_cancel_btn')
.fontColor($r('sys.color.ohos_id_color_text_primary'))
.fontSize($r('sys.float.ohos_id_text_size_button1'))
.fontFamily($r('sys.string.ohos_id_text_font_family_medium'))
.backgroundColor(Color.Transparent)
.fontWeight(FontWeight.Medium)
.focusable(true)
.focusOnTouch(true)
.constraintSize({ minHeight: 40, maxWidth: 400 })
.width('50%')
.onClick(() => {
hilog.info(this.domainId, this.logTag, 'AgreementDialog cancel.');
this.cancel();
})
Button('同意并登录',
{ type: ButtonType.Capsule, stateEffect: true })
.id('loginPanel_agreement_dialog_huawei_id_login_btn')
.fontColor(Color.White)
.backgroundColor('#CE0E2D')
.fontSize($r('sys.float.ohos_id_text_size_button1'))
.fontFamily($r('sys.string.ohos_id_text_font_family_medium'))
.fontWeight(FontWeight.Medium)
.focusable(true)
.focusOnTouch(true)
.constraintSize({ minHeight: 40, maxWidth: 400 })
.width('50%')
.onClick(() => {
hilog.info(this.domainId, this.logTag, 'AgreementDialog confirm.');
this.confirm();
})
}
.margin({
top: 8,
left: $r('sys.float.ohos_id_elements_margin_horizontal_l'),
right: $r('sys.float.ohos_id_elements_margin_horizontal_l'),
bottom: 16
})
}.backgroundColor($r('sys.color.ohos_id_color_dialog_default_bg'))
.padding({
left: 16,
right: 16
})
}
}
export enum ErrorCode {
// 账号未登录
ERROR_CODE_LOGIN_OUT = 1001502001,
// 该账号不支持一键登录,如海外账号
ERROR_CODE_NOT_SUPPORTED = 1001500003,
// 网络错误
ERROR_CODE_NETWORK_ERROR = 1001502005,
// 用户未同意用户协议
ERROR_CODE_AGREEMENT_STATUS_NOT_ACCEPTED = 1005300001,
// 参数错误
ERROR_CODE_PARAMETER_ERROR = 401
}

View File

@ -0,0 +1,40 @@
/*
* Copyright (c) 2023-2025 Haitai FangYuan Co., Ltd.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
@Entry
@Component
struct StatusBarPage {
build() {
Row() {
Column() {}
.width('100%')
}
.height('100%')
}
}

View File

@ -0,0 +1,43 @@
/*
* Copyright (c) 2023-2025 Haitai FangYuan Co., Ltd.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import { WebSubWindow } from 'web_engine';
let subStorage = LocalStorage.getShared();
@Entry(subStorage)
@Component
struct SubWindow {
build() {
Column() {
WebSubWindow()
}
.width('100%')
.height('100%')
}
}

View File

@ -0,0 +1,91 @@
import { webview } from '@kit.ArkWeb';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { router } from '@kit.ArkUI';
// 华为账号用户认证协议展示页
@Entry
@Component
export struct WebPage {
@State webUrl?: string = '';
@State progress: number = 0;
logTag: string = 'WebPage';
domainId: number = 0x0000;
controller: webview.WebviewController = new webview.WebviewController();
build() {
Column() {
Column() {
Button({ type: ButtonType.Normal }) {
Image($r('sys.media.ohos_ic_compnent_titlebar_back'))
.backgroundColor(Color.Transparent)
.borderRadius(20)
.width(24)
.height(24)
.draggable(false)
.autoResize(false)
.focusable(true)
.fillColor($r('sys.color.ohos_id_color_titlebar_icon'))
.matchTextDirection(true)
}
.alignSelf(ItemAlign.Start)
.backgroundColor($r('sys.color.ohos_id_color_button_normal'))
.borderRadius(20)
.width(40)
.height(40)
.onClick(() => {
router.back();
})
}
.height(56)
.width('100%')
.justifyContent(FlexAlign.Center)
.margin({
top: 36,
left: 16
})
Progress({ value: this.progress, type: ProgressType.Linear })
.width('100%')
.visibility(this.progress <= 99 ? Visibility.Visible : Visibility.None)
Web({ src: this.webUrl ?? '', controller: this.controller })
.backgroundColor(Color.Transparent)
.margin({ bottom: 60 })
.onProgressChange((event) => {
hilog.info(this.domainId, this.logTag,
'onProgressChange: ', (event ? event.newProgress : -1));
this.progress = event ? event.newProgress : 0;
})
.darkMode(WebDarkMode.Auto)
.forceDarkAccess(true)
.onLoadIntercept((event) => {
hilog.info(this.domainId, this.logTag, 'onLoadIntercept');
return false;
})
.onErrorReceive((event) => {
if (event) {
hilog.error(this.domainId, this.logTag, `onErrorReceive,errorInfo: ${event?.error?.getErrorInfo()}`);
}
})
}
.backgroundColor(0xffffff)
.alignItems(HorizontalAlign.Start)
.padding({ left: 12, right: 12, bottom: 60 })
.width('100%')
.height('100%')
}
aboutToAppear(): void {
hilog.info(this.domainId, this.logTag, 'aboutToAppear');
const params = router.getParams() as Record<string, string>;
this.webUrl = params.url ?? '';
hilog.info(this.domainId, this.logTag, `webUrl: ${this.webUrl}`);
}
aboutToDisappear(): void {
hilog.info(this.domainId, this.logTag, 'aboutToDisappear');
if (this.webUrl) {
this.controller.stop();
}
}
}

View File

@ -0,0 +1,50 @@
/*
* Copyright (c) 2023-2025 Haitai FangYuan Co., Ltd.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import { WebWindowNode } from 'web_engine';
import { KeyCode } from '@kit.InputKit';
let storage = LocalStorage.getShared();
@Entry(storage)
@Component
struct WindowNode {
build() {
Row() {
WebWindowNode()
}.onKeyEvent((event?: KeyEvent) => {
if (event) {
if (event.type == KeyType.Down && event.keyCode == KeyCode.KEYCODE_ESCAPE) {
event.stopPropagation();
}
}
})
.width('100%')
.height('100%')
}
}

View File

@ -0,0 +1,40 @@
/*
* Copyright (c) 2023-2025 Haitai FangYuan Co., Ltd.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import { WebChildProcess } from 'web_engine/childProcess';
export default class CustomChildProcess extends WebChildProcess {
onStart(): void {
super.onStart();
}
static toString(): string {
return "CustomChildProcess";
}
}

95
electron/src/main/module.json5 Executable file
View File

@ -0,0 +1,95 @@
{
"module": {
"name": "electron",
"type": "entry",
"srcEntry": "./ets/Application/AbilityStage.ets",
"description": "$string:module_desc",
"mainElement": "EntryAbility",
"deviceTypes": [
"2in1",
"tablet"
],
"deliveryWithInstall": true,
"installationFree": false,
"pages": "$profile:main_pages",
"metadata": [
{
"name": "client_id",
"value": ""
}
],
"abilities": [
{
"name": "EntryAbility",
"srcEntry": "./ets/entryability/EntryAbility.ets",
"description": "$string:EntryAbility_desc",
"icon": "$media:app_icon",
"label": "$string:EntryAbility_label",
"startWindowIcon": "$media:startIcon",
"startWindowBackground": "$color:start_window_background",
"launchType": "specified",
"removeMissionAfterTerminate": true,
"exported": true,
"skills": [
{
"entities": [
"entity.system.home",
"entity.system.browsable"
],
"actions": [
"action.system.home",
"ohos.want.action.viewData"
],
"uris": []
}
],
},
{
"name": "BrowserAbility",
"srcEntry": "./ets/entryability/BrowserAbility.ets",
"description": "$string:BrowserAbility_desc",
"startWindowIcon": "$media:app_icon",
"startWindowBackground": "$color:start_window_background",
"removeMissionAfterTerminate": true,
"exported": false,
"skills": [
{
"actions": [
"ohos.want.action.viewData"
],
"uris": []
}
],
"process": ':browser'
},
{
"name": "StatelessAbility",
"srcEntry": "./ets/entryability/StatelessAbility.ets",
"description": "$string:StatelessAbility_desc",
"label": "$string:StatelessAbility_label",
"startWindowIcon": "$media:app_icon",
"startWindowBackground": "$color:start_window_background",
"launchType": "specified",
"removeMissionAfterTerminate": true,
"exported": true,
"process": ':browser'
}
],
"extensionAbilities": [
{
"name": "StatusBarEntryAbility",
"icon": "$media:app_icon",
"description": "$string:StatusBarEntryAbility_desc",
"type": "statusBarView",
"exported": false,
"srcEntry": "./ets/entryability/StatusBarEntryAbility.ets"
},
{
"name": "BrowserEmbeddedAbility",
"srcEntry": "./ets/extensionAbility/BrowserEmbeddedAbility.ets",
"type": "embeddedUI",
"exported": false,
}
]
}
}

View File

@ -0,0 +1,20 @@
{
"color": [
{
"name": "start_window_background",
"value": "#FFFFFF"
},
{
"name": "button_background",
"value": "#007DFF"
},
{
"name": "button_font",
"value": "#FFFFFF"
},
{
"name": "checkbox_selected",
"value": "#007DFF"
}
]
}

View File

@ -0,0 +1,48 @@
{
"string": [
{
"name": "module_desc",
"value": "module description"
},
{
"name": "EntryAbility_desc",
"value": "description"
},
{
"name": "EntryAbility_label",
"value": "Electron"
},
{
"name": "BrowserAbility_desc",
"value": "description"
},
{
"name": "BrowserAbility_label",
"value": "BrowserAbility"
},
{
"name": "button_ok",
"value": "ok"
},
{
"name": "button_cancel",
"value": "cancel"
},
{
"name": "StatusBarEntryAbility_desc",
"value": "Application status bar"
},
{
"name": "StatusBarEntryAbility_label",
"value": "Application status bar"
},
{
"name": "StatelessAbility_desc",
"value": "description"
},
{
"name": "StatelessAbility_label",
"value": "StatelessAbility"
}
]
}

View File

@ -0,0 +1,11 @@
{
"src": [
"pages/Index",
"pages/SubWindow",
"pages/StatusBarPage",
"pages/EmbeddedWindow",
"pages/WindowNode",
"pages/Login",
"pages/WebPage"
]
}

View File

@ -0,0 +1,32 @@
{
"string": [
{
"name": "module_desc",
"value": "module description"
},
{
"name": "EntryAbility_desc",
"value": "description"
},
{
"name": "EntryAbility_label",
"value": "Electron"
},
{
"name": "button_ok",
"value": "ok"
},
{
"name": "button_cancel",
"value": "cancel"
},
{
"name": "StatusBarEntryAbility_desc",
"value": "Application status bar"
},
{
"name": "StatusBarEntryAbility_label",
"value": "Application status bar"
}
]
}

View File

@ -0,0 +1,32 @@
{
"string": [
{
"name": "module_desc",
"value": "模块描述"
},
{
"name": "EntryAbility_desc",
"value": "description"
},
{
"name": "EntryAbility_label",
"value": "Electron"
},
{
"name": "button_ok",
"value": "确认"
},
{
"name": "button_cancel",
"value": "取消"
},
{
"name": "StatusBarEntryAbility_desc",
"value": "应用状态栏"
},
{
"name": "StatusBarEntryAbility_label",
"value": "应用状态栏"
}
]
}

View File

@ -0,0 +1,35 @@
import hilog from '@ohos.hilog';
import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium';
export default function abilityTest() {
describe('ActsAbilityTest', () => {
// Defines a test suite. Two parameters are supported: test suite name and test suite function.
beforeAll(() => {
// Presets an action, which is performed only once before all test cases of the test suite start.
// This API supports only one parameter: preset action function.
})
beforeEach(() => {
// Presets an action, which is performed before each unit test case starts.
// The number of execution times is the same as the number of test cases defined by **it**.
// This API supports only one parameter: preset action function.
})
afterEach(() => {
// Presets a clear action, which is performed after each unit test case ends.
// The number of execution times is the same as the number of test cases defined by **it**.
// This API supports only one parameter: clear action function.
})
afterAll(() => {
// Presets a clear action, which is performed after all test cases of the test suite end.
// This API supports only one parameter: clear action function.
})
it('assertContain', 0, () => {
// Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function.
hilog.info(0x0000, 'testTag', '%{public}s', 'it begin');
let a = 'abc';
let b = 'b';
// Defines a variety of assertion methods, which are used to declare expected boolean conditions.
expect(a).assertContain(b);
expect(a).assertEqual(a);
})
})
}

View File

@ -0,0 +1,5 @@
import abilityTest from './Ability.test';
export default function testsuite() {
abilityTest();
}

View File

@ -0,0 +1,50 @@
import UIAbility from '@ohos.app.ability.UIAbility';
import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry';
import hilog from '@ohos.hilog';
import { Hypium } from '@ohos/hypium';
import testsuite from '../test/List.test';
import window from '@ohos.window';
import Want from '@ohos.app.ability.Want';
import AbilityConstant from '@ohos.app.ability.AbilityConstant';
export default class TestAbility extends UIAbility {
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) {
hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onCreate');
hilog.info(0x0000, 'testTag', '%{public}s', 'want param:' + JSON.stringify(want) ?? '');
hilog.info(0x0000, 'testTag', '%{public}s', 'launchParam:' + JSON.stringify(launchParam) ?? '');
let abilityDelegator: AbilityDelegatorRegistry.AbilityDelegator;
abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator();
let abilityDelegatorArguments: AbilityDelegatorRegistry.AbilityDelegatorArgs;
abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments();
hilog.info(0x0000, 'testTag', '%{public}s', 'start run testcase!!!');
Hypium.hypiumTest(abilityDelegator, abilityDelegatorArguments, testsuite);
}
onDestroy() {
hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onDestroy');
}
onWindowStageCreate(windowStage: window.WindowStage) {
hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onWindowStageCreate');
windowStage.loadContent('testability/pages/Index', (err, data) => {
if (err.code) {
hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
return;
}
hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s',
JSON.stringify(data) ?? '');
});
}
onWindowStageDestroy() {
hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onWindowStageDestroy');
}
onForeground() {
hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onForeground');
}
onBackground() {
hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onBackground');
}
}

View File

@ -0,0 +1,17 @@
@Entry
@Component
struct Index {
@State message: string = 'Hello World';
build() {
Row() {
Column() {
Text(this.message)
.fontSize(50)
.fontWeight(FontWeight.Bold)
}
.width('100%')
}
.height('100%')
}
}

View File

@ -0,0 +1,47 @@
import hilog from '@ohos.hilog';
import TestRunner from '@ohos.application.testRunner';
import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry';
import Want from '@ohos.app.ability.Want';
let abilityDelegator: AbilityDelegatorRegistry.AbilityDelegator | undefined = undefined
let abilityDelegatorArguments: AbilityDelegatorRegistry.AbilityDelegatorArgs | undefined = undefined
async function onAbilityCreateCallback() {
hilog.info(0x0000, 'testTag', '%{public}s', 'onAbilityCreateCallback');
}
async function addAbilityMonitorCallback(err : Error) {
hilog.info(0x0000, 'testTag', 'addAbilityMonitorCallback : %{public}s', JSON.stringify(err) ?? '');
}
export default class OpenHarmonyTestRunner implements TestRunner {
constructor() {
}
onPrepare() {
hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner OnPrepare ');
}
async onRun() {
hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner onRun run');
abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments()
abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator()
const bundleName = abilityDelegatorArguments.bundleName;
const testAbilityName = 'TestAbility';
let lMonitor: AbilityDelegatorRegistry.AbilityMonitor = {
abilityName: testAbilityName,
onAbilityCreate: onAbilityCreateCallback,
};
abilityDelegator.addAbilityMonitor(lMonitor, addAbilityMonitorCallback)
const want: Want = {
bundleName: bundleName,
abilityName: testAbilityName
};
abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator();
abilityDelegator.startAbility(want, (err, data) => {
hilog.info(0x0000, 'testTag', 'startAbility : err : %{public}s', JSON.stringify(err) ?? '');
hilog.info(0x0000, 'testTag', 'startAbility : data : %{public}s',JSON.stringify(data) ?? '');
})
hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner onRun end');
}
}

View File

@ -0,0 +1,36 @@
{
"module": {
"name": "pc_test",
"type": "feature",
"description": "$string:module_test_desc",
"mainElement": "TestAbility",
"deviceTypes": [
"2in1"
],
"deliveryWithInstall": true,
"installationFree": false,
"pages": "$profile:test_pages",
"abilities": [
{
"name": "TestAbility",
"srcEntry": "./ets/testability/TestAbility.ets",
"description": "$string:TestAbility_desc",
"icon": "$media:icon",
"label": "$string:TestAbility_label",
"exported": true,
"startWindowIcon": "$media:icon",
"startWindowBackground": "$color:start_window_background",
"skills": [
{
"actions": [
"action.system.home"
],
"entities": [
"entity.system.home"
]
}
]
}
]
}
}

View File

@ -0,0 +1,8 @@
{
"color": [
{
"name": "start_window_background",
"value": "#FFFFFF"
}
]
}

View File

@ -0,0 +1,16 @@
{
"string": [
{
"name": "module_test_desc",
"value": "test ability description"
},
{
"name": "TestAbility_desc",
"value": "the test ability"
},
{
"name": "TestAbility_label",
"value": "test label"
}
]
}

View File

@ -0,0 +1,5 @@
{
"src": [
"testability/pages/Index"
]
}

View File

@ -0,0 +1,5 @@
import localUnitTest from './LocalUnit.test';
export default function testsuite() {
localUnitTest();
}

View File

@ -0,0 +1,33 @@
import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium';
export default function localUnitTest() {
describe('localUnitTest',() => {
// Defines a test suite. Two parameters are supported: test suite name and test suite function.
beforeAll(() => {
// Presets an action, which is performed only once before all test cases of the test suite start.
// This API supports only one parameter: preset action function.
});
beforeEach(() => {
// Presets an action, which is performed before each unit test case starts.
// The number of execution times is the same as the number of test cases defined by **it**.
// This API supports only one parameter: preset action function.
});
afterEach(() => {
// Presets a clear action, which is performed after each unit test case ends.
// The number of execution times is the same as the number of test cases defined by **it**.
// This API supports only one parameter: clear action function.
});
afterAll(() => {
// Presets a clear action, which is performed after all test cases of the test suite end.
// This API supports only one parameter: clear action function.
});
it('assertContain', 0, () => {
// Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function.
let a = 'abc';
let b = 'b';
// Defines a variety of assertion methods, which are used to declare expected boolean conditions.
expect(a).assertContain(b);
expect(a).assertEqual(a);
});
});
}

17
hvigor/hvigor-config.json5 Executable file
View File

@ -0,0 +1,17 @@
{
"modelVersion": "5.0.0",
"dependencies": {
},
"execution": {
// "daemon": true, /* Enable daemon compilation. Default: true */
// "incremental": true, /* Enable incremental compilation. Default: true */
// "parallel": true, /* Enable parallel compilation. Default: true */
// "typeCheck": false, /* Enable typeCheck. Default: false */
},
"logging": {
// "level": "info" /* Define the log level. Value: [ "debug" | "info" | "warn" | "error" ]. Default: "info" */
},
"debugging": {
// "stacktrace": false /* Disable stacktrace compilation. Default: false */
}
}

6
hvigorfile.ts Normal file
View File

@ -0,0 +1,6 @@
import { appTasks } from '@ohos/hvigor-ohos-plugin';
export default {
system: appTasks, /* Built-in plugin of Hvigor. It cannot be modified. */
plugins:[] /* Custom plugin to extend the functionality of Hvigor. */
}

21
oh-package-lock.json5 Normal file
View File

@ -0,0 +1,21 @@
{
"meta": {
"stableOrder": true,
"enableUnifiedLockfile": false
},
"lockfileVersion": 3,
"ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.",
"specifiers": {
"@ohos/hypium@1.0.6": "@ohos/hypium@1.0.6"
},
"packages": {
"@ohos/hypium@1.0.6": {
"name": "@ohos/hypium",
"version": "1.0.6",
"integrity": "sha512-bb3DWeWhYrFqj9mPFV3yZQpkm36kbcK+YYaeY9g292QKSjOdmhEIQR2ULPvyMsgSR4usOBf5nnYrDmaCCXirgQ==",
"resolved": "https://ohpm.openharmony.cn/ohpm/@ohos/hypium/-/hypium-1.0.6.tgz",
"shasum": "3f5fed65372633233264b3447705b0831dfe7ea1",
"registryType": "ohpm"
}
}
}

13
oh-package.json5 Normal file
View File

@ -0,0 +1,13 @@
{
"modelVersion": "5.0.0",
"license": "",
"devDependencies": {
"@ohos/hypium": "1.0.6"
},
"author": "",
"name": "ohos_hap",
"description": "Please describe the basic information.",
"main": "",
"version": "1.0.0",
"dependencies": {}
}

View File

@ -0,0 +1,17 @@
/**
* Use these variables when you tailor your ArkTS code. They must be of the const type.
*/
export const HAR_VERSION = '1.0.0';
export const BUILD_MODE_NAME = 'debug';
export const DEBUG = true;
export const TARGET_NAME = 'default';
/**
* BuildProfile Class is used only for compatibility purposes.
*/
export default class BuildProfile {
static readonly HAR_VERSION = HAR_VERSION;
static readonly BUILD_MODE_NAME = BUILD_MODE_NAME;
static readonly DEBUG = DEBUG;
static readonly TARGET_NAME = TARGET_NAME;
}

9
web_engine/Index.ets Normal file
View File

@ -0,0 +1,9 @@
export { WebAbilityStage } from './src/main/ets/application/WebAbilityStage';
export { WebAbility } from './src/main/ets/ability/WebAbility';
export { WebEmbeddedAbility } from './src/main/ets/ability/WebEmbeddedAbility';
export { WebWindow } from './src/main/ets/components/WebWindow';
export { WebSubWindow } from './src/main/ets/components/WebSubWindow';
export { WebEmbeddedWindow } from './src/main/ets/components/WebEmbeddedWindow';
export { WebWindowNode } from './src/main/ets/components/WebWindowNode';
export { ILoginInfo } from './src/main/ets/interface/CommonInterface';
export { ILogin } from './src/main/ets/interface/CommonInterface';

View File

@ -0,0 +1,28 @@
{
"apiType": "stageMode",
"buildOption": {
},
"buildOptionSet": [
{
"name": "release",
"arkOptions": {
"obfuscation": {
"ruleOptions": {
"enable": true,
"files": [
"./obfuscation-rules.txt"
]
},
"consumerFiles": [
"./consumer-rules.txt"
]
}
}
},
],
"targets": [
{
"name": "default"
}
]
}

1
web_engine/childProcess.ets Executable file
View File

@ -0,0 +1 @@
export { WebChildProcess } from './src/main/ets/process/WebChildProcess';

View File

6
web_engine/hvigorfile.ts Normal file
View File

@ -0,0 +1,6 @@
import { harTasks } from '@ohos/hvigor-ohos-plugin';
export default {
system: harTasks, /* Built-in plugin of Hvigor. It cannot be modified. */
plugins:[] /* Custom plugin to extend the functionality of Hvigor. */
}

View File

@ -0,0 +1,18 @@
# Define project specific obfuscation rules here.
# You can include the obfuscation configuration files in the current module's build-profile.json5.
#
# For more details, see
# https://gitee.com/openharmony/arkcompiler_ets_frontend/blob/master/arkguard/README.md
# Obfuscation options:
# -disable-obfuscation: disable all obfuscations
# -enable-property-obfuscation: obfuscate the property names
# -enable-toplevel-obfuscation: obfuscate the names in the global scope
# -compact: remove unnecessary blank spaces and all line feeds
# -remove-log: remove all console.* statements
# -print-namecache: print the name cache that contains the mapping from the old names to new names
# -apply-namecache: reuse the given cache file
# Keep options:
# -keep-property-name: specifies property names that you want to keep
# -keep-global-name: specifies names that you want to keep in the global scope

View File

@ -0,0 +1,37 @@
{
"meta": {
"stableOrder": true,
"enableUnifiedLockfile": false
},
"lockfileVersion": 3,
"ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.",
"specifiers": {
"inversify@^6.0.1": "inversify@6.0.1",
"libadapter.so@src/main/cpp/types/libadapter": "libadapter.so@src/main/cpp/types/libadapter",
"reflect-metadata@^0.1.13": "reflect-metadata@0.2.1"
},
"packages": {
"inversify@6.0.1": {
"name": "inversify",
"version": "6.0.1",
"integrity": "sha512-B3ex30927698TJENHR++8FfEaJGqoWOgI6ZY5Ht/nLUsFCwHn6akbwtnUAPCgUepAnTpe2qHxhDNjoKLyz6rgQ==",
"resolved": "https://ohpm.openharmony.cn/ohpm/inversify/-/inversify-6.0.1.tgz",
"shasum": "b20d35425d5d8c5cd156120237aad0008d969f02",
"registryType": "ohpm"
},
"libadapter.so@src/main/cpp/types/libadapter": {
"name": "libadapter.so",
"version": "0.0.0",
"resolved": "src/main/cpp/types/libadapter",
"registryType": "local"
},
"reflect-metadata@0.2.1": {
"name": "reflect-metadata",
"version": "0.2.1",
"integrity": "sha512-i5lLI6iw9AU3Uu4szRNPPEkomnkjRTaVt9hy/bn5g/oSzekBSMeLZblcjP74AW0vBabqERLLIrz+gR8QYR54Tw==",
"resolved": "https://ohpm.openharmony.cn/ohpm/reflect-metadata/-/reflect-metadata-0.2.1.tgz",
"shasum": "8d5513c0f5ef2b4b9c3865287f3c0940c1f67f74",
"registryType": "ohpm"
}
}
}

View File

@ -0,0 +1,15 @@
{
"name": "web_engine",
"version": "1.0.0",
"description": "Please describe the basic information.",
"main": "Index.ets",
"author": "",
"license": "Apache-2.0",
"devDependencies": {
'libadapter.so': 'file:./src/main/cpp/types/libadapter',
},
"dependencies": {
"inversify": "^6.0.1",
"reflect-metadata": "^0.1.13"
}
}

Some files were not shown because too many files have changed in this diff Show More