openharmony: add servoshell for ohos (#33295)

* openharmony: add servoshell for ohos

Signed-off-by: Mukilan Thiyagarajan <mukilan@igalia.com>

* ohos: handle missing signing config on forks

Signed-off-by: Mukilan Thiyagarajan <mukilan@igalia.com>

---------

Signed-off-by: Mukilan Thiyagarajan <mukilan@igalia.com>
This commit is contained in:
Mukilan Thiyagarajan 2024-09-20 13:50:27 +05:30 committed by GitHub
parent 457d37d94e
commit 157e28c59b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
31 changed files with 625 additions and 9 deletions

1
.gitattributes vendored
View file

@ -1,5 +1,6 @@
* text=auto eol=lf * text=auto eol=lf
tests/wpt/** linguist-vendored tests/wpt/** linguist-vendored
support/openharmony/**/*.ets linguist-language=ts
# Denote all files that are truly binary and should not be modified. # Denote all files that are truly binary and should not be modified.
*.png binary *.png binary

View file

@ -57,6 +57,7 @@ jobs:
uses: ./.github/workflows/ohos.yml uses: ./.github/workflows/ohos.yml
with: with:
profile: "release" profile: "release"
secrets: inherit
build-result: build-result:
name: Result name: Result

View file

@ -55,9 +55,32 @@ jobs:
uses: openharmony-rs/setup-ohos-sdk@v0.1 uses: openharmony-rs/setup-ohos-sdk@v0.1
with: with:
version: "4.1" version: "4.1"
components: "native;toolchains;ets;js;previewer"
fixup-path: true
- name: Install node for hvigor
uses: actions/setup-node@v4
with:
node-version: 18
- name: Install hvigor modules
run: |
mkdir ~/hvigor-installation
cd ~/hvigor-installation
echo "@ohos:registry=https://repo.harmonyos.com/npm/" > .npmrc
npm install "@ohos/hvigor@5" "@ohos/hvigor-ohos-plugin@5"
echo "HVIGOR_PATH=$PWD" >> $GITHUB_ENV
- name: "Setup HAP signing config"
env:
SIGNING_MATERIAL: ${{ secrets.SERVO_OHOS_SIGNING_MATERIAL }}
if: ${{ env.SIGNING_MATERIAL != '' }} # Allows the build to pass on forks.
run: |
cd ~
echo "${SIGNING_MATERIAL}" | base64 -d > servo-ohos-material.zip
unzip servo-ohos-material.zip
echo "SERVO_OHOS_SIGNING_CONFIG=${PWD}/servo-ohos-material/signing-configs.json" >> $GITHUB_ENV
- name: Build (arch ${{ matrix.arch }} profile ${{ inputs.profile }}) - name: Build (arch ${{ matrix.arch }} profile ${{ inputs.profile }})
env: env:
OHOS_SDK_NATIVE: ${{ steps.setup_sdk.outputs.ohos_sdk_native }} OHOS_SDK_NATIVE: ${{ steps.setup_sdk.outputs.ohos_sdk_native }}
OHOS_BASE_SDK_HOME: ${{ steps.setup_sdk.outputs.ohos-base-sdk-home }}
run: | run: |
python3 ./mach build --locked --target ${{ matrix.arch }} --${{ inputs.profile }} python3 ./mach build --locked --target ${{ matrix.arch }} --${{ inputs.profile }}
cp -r target/cargo-timings target/cargo-timings-ohos-${{ matrix.arch }} cp -r target/cargo-timings target/cargo-timings-ohos-${{ matrix.arch }}
@ -67,3 +90,15 @@ jobs:
name: cargo-timings-ohos-${{ matrix.arch }} name: cargo-timings-ohos-${{ matrix.arch }}
# Using a wildcard here ensures that the archive includes the path. # Using a wildcard here ensures that the archive includes the path.
path: target/cargo-timings-* path: target/cargo-timings-*
- name: Upload signed HAP artifact
if: ${{ env.SERVO_OHOS_SIGNING_CONFIG != '' }} # Build output has different name if not signed.
uses: actions/upload-artifact@v4
with:
name: ${{ inputs.profile }}-binary-ohos-${{ matrix.arch }}
path: target/openharmony/${{ matrix.arch }}/${{ inputs.profile }}/entry/build/default/outputs/default/servoshell-default-signed.hap
- name: Upload unsigned HAP artifact
if: ${{ env.SERVO_OHOS_SIGNING_CONFIG == '' }} # Build output has different name if not signed.
uses: actions/upload-artifact@v4
with:
name: ${{ inputs.profile }}-binary-ohos-${{ matrix.arch }}
path: target/openharmony/${{ matrix.arch }}/${{ inputs.profile }}/entry/build/default/outputs/default/servoshell-default-unsigned.hap

View file

@ -297,6 +297,7 @@ class CommandBase(object):
self.config.setdefault("build", {}) self.config.setdefault("build", {})
self.config["build"].setdefault("android", False) self.config["build"].setdefault("android", False)
self.config["build"].setdefault("ohos", False)
self.config["build"].setdefault("mode", "") self.config["build"].setdefault("mode", "")
self.config["build"].setdefault("debug-assertions", False) self.config["build"].setdefault("debug-assertions", False)
self.config["build"].setdefault("debug-mozjs", False) self.config["build"].setdefault("debug-mozjs", False)
@ -328,12 +329,6 @@ class CommandBase(object):
def get_top_dir(self): def get_top_dir(self):
return self.context.topdir return self.context.topdir
def get_apk_path(self, build_type: BuildType):
base_path = util.get_target_dir()
base_path = path.join(base_path, "android", self.target.triple())
apk_name = "servoapp.apk"
return path.join(base_path, build_type.directory_name(), apk_name)
def get_binary_path(self, build_type: BuildType, asan: bool = False): def get_binary_path(self, build_type: BuildType, asan: bool = False):
base_path = util.get_target_dir() base_path = util.get_target_dir()
if asan or self.target.is_cross_build(): if asan or self.target.is_cross_build():
@ -551,7 +546,12 @@ class CommandBase(object):
CommandArgument( CommandArgument(
'--android', default=None, action='store_true', '--android', default=None, action='store_true',
help='Build for Android. If --target is not specified, this ' help='Build for Android. If --target is not specified, this '
'will choose a default target architecture.', f'will choose the default target architecture ({AndroidTarget.DEFAULT_TRIPLE}).',
),
CommandArgument(
'--ohos', default=None, action='store_true',
help='Build for OpenHarmony. If --target is not specified, this '
f'will choose a default target architecture ({OpenHarmonyTarget.DEFAULT_TRIPLE}).',
), ),
CommandArgument('--win-arm64', action='store_true', help="Use arm64 Windows target"), CommandArgument('--win-arm64', action='store_true', help="Use arm64 Windows target"),
CommandArgumentGroup('Feature Selection'), CommandArgumentGroup('Feature Selection'),
@ -646,6 +646,7 @@ class CommandBase(object):
self.configure_build_target(kwargs, suppress_log=True) self.configure_build_target(kwargs, suppress_log=True)
kwargs.pop('target', False) kwargs.pop('target', False)
kwargs.pop('android', False) kwargs.pop('android', False)
kwargs.pop('ohos', False)
return original_function(self, *args, **kwargs) return original_function(self, *args, **kwargs)
return target_configuration_decorator return target_configuration_decorator
@ -686,15 +687,28 @@ class CommandBase(object):
return return
android = kwargs.get('android') or self.config["build"]["android"] android = kwargs.get('android') or self.config["build"]["android"]
ohos = kwargs.get('ohos') or self.config["build"]["ohos"]
target_triple = kwargs.get('target') target_triple = kwargs.get('target')
if android and ohos:
print("Cannot build both android and ohos targets simultaneously.")
sys.exit(1)
if android and target_triple: if android and target_triple:
print("Please specify either --target or --android.") print("Please specify either --target or --android.")
sys.exit(1) sys.exit(1)
# Set the default Android target # Set the default Android target
if android and not target_triple: if android and not target_triple:
target_triple = "aarch64-linux-android" target_triple = AndroidTarget.DEFAULT_TRIPLE
if ohos and target_triple:
print("Please specify either --target or --ohos.")
sys.exit(1)
# Set the default OpenHarmony target
if ohos and not target_triple:
target_triple = OpenHarmonyTarget.DEFAULT_TRIPLE
self.target = BuildTarget.from_triple(target_triple) self.target = BuildTarget.from_triple(target_triple)
@ -705,6 +719,9 @@ class CommandBase(object):
def is_android(self): def is_android(self):
return isinstance(self.target, AndroidTarget) return isinstance(self.target, AndroidTarget)
def is_openharmony(self):
return isinstance(self.target, OpenHarmonyTarget)
def is_media_enabled(self, media_stack: Optional[str]): def is_media_enabled(self, media_stack: Optional[str]):
"""Determine whether media is enabled based on the value of the build target """Determine whether media is enabled based on the value of the build target
platform and the value of the '--media-stack' command-line argument. platform and the value of the '--media-stack' command-line argument.

View file

@ -35,6 +35,7 @@ from servo.command_base import (
archive_deterministically, archive_deterministically,
BuildNotFound, BuildNotFound,
cd, cd,
check_output,
CommandBase, CommandBase,
is_windows, is_windows,
) )
@ -124,6 +125,10 @@ class PackageCommands(CommandBase):
default=None, default=None,
action='store_true', action='store_true',
help='Package Android') help='Package Android')
@CommandArgument('--ohos',
default=None,
action='store_true',
help='Package OpenHarmony')
@CommandArgument('--target', '-t', @CommandArgument('--target', '-t',
default=None, default=None,
help='Package for given target platform') help='Package for given target platform')
@ -178,6 +183,55 @@ class PackageCommands(CommandBase):
except subprocess.CalledProcessError as e: except subprocess.CalledProcessError as e:
print("Packaging Android exited with return value %d" % e.returncode) print("Packaging Android exited with return value %d" % e.returncode)
return e.returncode return e.returncode
elif self.is_openharmony():
# hvigor doesn't support an option to place output files in a specific directory
# so copy the source files into the target/openharmony directory first.
ohos_app_dir = path.join(self.get_top_dir(), "support", "openharmony")
build_mode = build_type.directory_name()
ohos_target_dir = path.join(
self.get_top_dir(), "target", "openharmony", self.target.triple(), build_mode)
if path.exists(ohos_target_dir):
print("Cleaning up from previous packaging")
delete(ohos_target_dir)
shutil.copytree(ohos_app_dir, ohos_target_dir)
# Map non-debug profiles to 'release' buildMode HAP.
if build_type.is_custom():
build_mode = "release"
hvigor_command = ["--no-daemon", "assembleHap", "-p", "product=default", "-p", f"buildMode={build_mode}"]
# Detect if PATH already has hvigor, or else fallback to npm installation
# provided via HVIGOR_PATH
if "HVIGOR_PATH" not in env:
try:
with cd(ohos_target_dir):
version = check_output(["hvigorw", "--version", "--no-daemon"])
print(f"Found `hvigorw` with version {str(version, 'utf-8').strip()} in system PATH")
hvigor_command[0:0] = ["hvigorw"]
except FileNotFoundError:
print("Unable to find `hvigor` tool. Please either modify PATH to include the"
"path to hvigorw or set the HVIGOR_PATH environment variable to the npm"
"installation containing `node_modules` directory with hvigor modules.")
sys.exit(1)
else:
env["NODE_PATH"] = env["HVIGOR_PATH"] + "/node_modules"
hvigor_script = f"{env['HVIGOR_PATH']}/node_modules/@ohos/hvigor/bin/hvigor.js"
hvigor_command[0:0] = ["node", hvigor_script]
abi_string = self.target.abi_string()
ohos_libs_dir = path.join(ohos_target_dir, "entry", "libs", abi_string)
os.makedirs(ohos_libs_dir)
# The libservoshell.so binary that was built needs to be copied
# into the app folder heirarchy where hvigor expects it.
print(f"Copying {binary_path} to {ohos_libs_dir}")
shutil.copy(binary_path, ohos_libs_dir)
try:
with cd(ohos_target_dir):
print("Calling", hvigor_command)
subprocess.check_call(hvigor_command, env=env)
except subprocess.CalledProcessError as e:
print("Packaging OpenHarmony exited with return value %d" % e.returncode)
return e.returncode
elif 'darwin' in self.target.triple(): elif 'darwin' in self.target.triple():
print("Creating Servo.app") print("Creating Servo.app")
dir_to_dmg = path.join(target_dir, 'dmg') dir_to_dmg = path.join(target_dir, 'dmg')
@ -347,6 +401,9 @@ class PackageCommands(CommandBase):
@CommandArgument('--android', @CommandArgument('--android',
action='store_true', action='store_true',
help='Install on Android') help='Install on Android')
@CommandArgument('--ohos',
action='store_true',
help='Install on OpenHarmony')
@CommandArgument('--emulator', @CommandArgument('--emulator',
action='store_true', action='store_true',
help='For Android, install to the only emulated device') help='For Android, install to the only emulated device')
@ -376,7 +433,7 @@ class PackageCommands(CommandBase):
return 1 return 1
if self.is_android(): if self.is_android():
pkg_path = self.get_apk_path(build_type) pkg_path = self.target.get_package_path(build_type.directory_name())
exec_command = [self.android_adb_path(env)] exec_command = [self.android_adb_path(env)]
if emulator and usb: if emulator and usb:
print("Cannot install to both emulator and USB at the same time.") print("Cannot install to both emulator and USB at the same time.")
@ -386,6 +443,10 @@ class PackageCommands(CommandBase):
if usb: if usb:
exec_command += ["-d"] exec_command += ["-d"]
exec_command += ["install", "-r", pkg_path] exec_command += ["install", "-r", pkg_path]
elif self.is_openharmony():
pkg_path = self.target.get_package_path(build_type.directory_name())
hdc_path = path.join(env["OHOS_SDK_NATIVE"], "../", "toolchains", "hdc")
exec_command = [hdc_path, "install", "-r", pkg_path]
elif is_windows(): elif is_windows():
pkg_path = path.join(path.dirname(binary_path), 'msi', 'Servo.msi') pkg_path = path.join(path.dirname(binary_path), 'msi', 'Servo.msi')
exec_command = ["msiexec", "/i", pkg_path] exec_command = ["msiexec", "/i", pkg_path]

View file

@ -21,6 +21,7 @@ from packaging.version import parse as parse_version
from typing import Any, Dict, Optional from typing import Any, Dict, Optional
import servo.platform import servo.platform
import servo.util as util
class BuildTarget(object): class BuildTarget(object):
@ -61,6 +62,8 @@ class CrossBuildTarget(BuildTarget):
class AndroidTarget(CrossBuildTarget): class AndroidTarget(CrossBuildTarget):
DEFAULT_TRIPLE = "aarch64-linux-android"
def ndk_configuration(self) -> Dict[str, str]: def ndk_configuration(self) -> Dict[str, str]:
target = self.triple() target = self.triple()
config = {} config = {}
@ -237,8 +240,16 @@ class AndroidTarget(CrossBuildTarget):
def needs_packaging(self) -> bool: def needs_packaging(self) -> bool:
return True return True
def get_package_path(self, build_type_directory: str) -> str:
base_path = util.get_target_dir()
base_path = path.join(base_path, "android", self.triple())
apk_name = "servoapp.apk"
return path.join(base_path, build_type_directory, apk_name)
class OpenHarmonyTarget(CrossBuildTarget): class OpenHarmonyTarget(CrossBuildTarget):
DEFAULT_TRIPLE = "aarch64-unknown-linux-ohos"
def configure_build_environment(self, env: Dict[str, str], config: Dict[str, Any], topdir: pathlib.Path): def configure_build_environment(self, env: Dict[str, str], config: Dict[str, Any], topdir: pathlib.Path):
# Paths to OpenHarmony SDK and build tools: # Paths to OpenHarmony SDK and build tools:
# Note: `OHOS_SDK_NATIVE` is the CMake variable name the `hvigor` build-system # Note: `OHOS_SDK_NATIVE` is the CMake variable name the `hvigor` build-system
@ -370,3 +381,17 @@ class OpenHarmonyTarget(CrossBuildTarget):
def needs_packaging(self) -> bool: def needs_packaging(self) -> bool:
return True return True
def get_package_path(self, build_type_directory: str) -> str:
base_path = util.get_target_dir()
base_path = path.join(base_path, "openharmony", self.triple())
hap_name = "servoshell-default-signed.hap"
build_output_path = path.join("entry", "build", "default", "outputs", "default")
return path.join(base_path, build_type_directory, build_output_path, hap_name)
def abi_string(self) -> str:
abi_map = {
"aarch64-unknown-linux-ohos": "arm64-v8a",
"x86_64-unknown-linux-ohos": "x86_64"
}
return abi_map[self.triple()]

View file

@ -0,0 +1,10 @@
{
"app": {
"bundleName": "org.servo.servoshell",
"vendor": "example",
"versionCode": 1000000,
"versionName": "1.0.0",
"icon": "$media:servo_64",
"label": "$string:app_name"
}
}

View file

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

View file

@ -0,0 +1 @@
../../../../../../resources/servo_64.png

View file

@ -0,0 +1,44 @@
{
"app": {
"products": [
{
"name": "default",
"signingConfig": "default",
"compileSdkVersion": 11,
"compatibleSdkVersion": 11,
"targetSdkVersion": 11,
"runtimeOS": "OpenHarmony"
},
{
"name": "harmonyos",
"signingConfig": "default",
"compatibleSdkVersion": "4.1.0(11)",
"targetSdkVersion": "4.1.0(11)",
"runtimeOS": "HarmonyOS"
}
],
"buildModeSet": [
{
"name": "debug"
},
{
"name": "release"
}
]
},
"modules": [
{
"name": "servoshell",
"srcPath": "./entry",
"targets": [
{
"name": "default",
"applyToProducts": [
"default",
"harmonyos"
]
}
]
}
]
}

View file

@ -0,0 +1,36 @@
{
"apiType": "stageMode",
"buildOption": {
"arkOptions": {
},
"externalNativeOptions": {
"path": "./src/main/cpp/CMakeLists.txt",
"arguments": "",
"cppFlags": "",
"abiFilters": ["arm64-v8a", "x86_64"]
}
},
"buildOptionSet": [
{
"name": "release",
"arkOptions": {
"obfuscation": {
"ruleOptions": {
"enable": true,
"files": [
"./obfuscation-rules.txt"
]
}
}
}
},
],
"targets": [
{
"name": "default"
},
{
"name": "ohosTest",
}
]
}

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. */
}

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,12 @@
{
"license": "Apache-2.0",
"devDependencies": {},
"author": "",
"name": "servoshell",
"description": "Please describe the basic information.",
"main": "",
"version": "1.0.0",
"dependencies": {
"libservoshell.so": "file:./src/main/cpp/types/libentry"
}
}

View file

@ -0,0 +1,3 @@
# the minimum version of CMake.
cmake_minimum_required(VERSION 3.4.1)
project(servoshell)

View file

@ -0,0 +1 @@
export const loadURL: (url: string) => void;

View file

@ -0,0 +1,6 @@
{
"name": "libservoshell.so",
"types": "./index.d.ts",
"version": "",
"description": "The native module which exposes a C API to servoshell"
}

View file

@ -0,0 +1,43 @@
import AbilityConstant from '@ohos.app.ability.AbilityConstant';
import hilog from '@ohos.hilog';
import UIAbility from '@ohos.app.ability.UIAbility';
import Want from '@ohos.app.ability.Want';
import window from '@ohos.window';
export default class EntryAbility extends UIAbility {
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) {
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');
}
onDestroy() {
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy');
}
onWindowStageCreate(windowStage: window.WindowStage) {
// Main window is created, set main page for this ability
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');
windowStage.loadContent('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() {
// Main window is destroyed, release UI related resources
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy');
}
onForeground() {
// Ability has brought to foreground
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground');
}
onBackground() {
// Ability has back to background
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground');
}
};

View file

@ -0,0 +1,85 @@
import display from '@ohos.display';
import deviceInfo from '@ohos.deviceInfo';
interface ServoXComponentInterface {
loadURL(url: string): void;
registerURLcallback(callback: (url: string) => void): void;
initServo(options: InitOpts): void;
}
interface InitOpts {
url: string;
deviceType: string,
osFullName: string,
displayDensity: number,
}
function get_density(): number {
try {
let displayClass = display.getDefaultDisplaySync();
console.info('Test densityDPI:' + JSON.stringify(displayClass.densityDPI));
return displayClass.densityDPI / 160;
} catch (exception) {
console.error('Failed to obtain the default display object. Code: ' + JSON.stringify(exception));
return 3;
}
}
function get_device_type(): string {
let device_type: string = deviceInfo.deviceType;
if (device_type == "") {
console.error("deviceInfo.deviceType is empty string!")
} else {
console.info("Device type is " + device_type)
}
return device_type;
}
@Entry
@Component
struct Index {
xComponentContext: ServoXComponentInterface | undefined = undefined;
xComponentAttrs: XComponentAttrs = {
id: 'ServoDemo',
type: XComponentType.SURFACE,
libraryname: 'servoshell',
}
@State urlToLoad: string = 'https://servo.org'
build() {
Column() {
TextInput({placeholder:'URL',text: $$this.urlToLoad})
.type(InputType.Normal)
.onChange((value) => {
this.urlToLoad = value
})
.onSubmit((EnterKeyType)=>{
this.xComponentContext?.loadURL(this.urlToLoad)
console.info('Load URL: ', this.urlToLoad)
})
XComponent(this.xComponentAttrs)
.focusable(true)
.onLoad((xComponentContext) => {
this.xComponentContext = xComponentContext as ServoXComponentInterface;
let init_options: InitOpts = {
url: this.urlToLoad,
deviceType: get_device_type(),
osFullName: deviceInfo.osFullName,
displayDensity: get_density()
}
this.xComponentContext.initServo(init_options)
this.xComponentContext.registerURLcallback((new_url) => {
console.info('New URL from native: ', new_url)
this.urlToLoad = new_url
})
})
}
.width('100%')
}
}
interface XComponentAttrs {
id: string;
type: number;
libraryname: string;
}

View file

@ -0,0 +1,52 @@
{
"module": {
"name": "servoshell",
"type": "entry",
"description": "$string:module_desc",
"mainElement": "EntryAbility",
"deviceTypes": [
"default"
],
"deliveryWithInstall": true,
"installationFree": false,
"pages": "$profile:main_pages",
"abilities": [
{
"name": "EntryAbility",
"srcEntry": "./ets/entryability/EntryAbility.ets",
"description": "$string:EntryAbility_desc",
"icon": "$media:servo_1024",
"label": "$string:EntryAbility_label",
"startWindowIcon": "$media:servo_64",
"startWindowBackground": "$color:start_window_background",
"exported": true,
"skills": [
{
"entities": [
"entity.system.home"
],
"actions": [
"action.system.home"
]
}
]
}
],
// ohos.permission.RUN_DYN_CODE - required for JIT?
"requestPermissions": [
{
"name": "ohos.permission.GET_NETWORK_INFO",
"reason": "$string:perm_reason",
},
{
"name": "ohos.permission.INTERNET",
"reason": "$string:perm_reason",
},
{
"name": "ohos.permission.KEEP_BACKGROUND_RUNNING",
"reason": "$string:perm_reason",
},
]
}
}

View file

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

View file

@ -0,0 +1,20 @@
{
"string": [
{
"name": "module_desc",
"value": "module description"
},
{
"name": "EntryAbility_desc",
"value": "description"
},
{
"name": "EntryAbility_label",
"value": "label"
},
{
"name": "perm_reason",
"value": "This is a demo app, and we need permissions"
}
]
}

View file

@ -0,0 +1 @@
../../../../../../../../resources/servo_1024.png

View file

@ -0,0 +1 @@
../../../../../../../../resources/servo_64.png

View file

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

View file

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

View file

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

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 */
}
}

View file

@ -0,0 +1,34 @@
import { appTasks, OhosAppContext, OhosPluginId } from '@ohos/hvigor-ohos-plugin';
import { getNode } from '@ohos/hvigor'
import * as fs from 'fs';
import * as path from 'path';
const rootNode = getNode(__filename);
rootNode.afterNodeEvaluate(node => {
const appContext = node.getContext(OhosPluginId.OHOS_APP_PLUGIN) as OhosAppContext;
const buildProfileOpt = appContext.getBuildProfileOpt();
const signingConfigsPath = process.env["SERVO_OHOS_SIGNING_CONFIG"];
if (signingConfigsPath) {
if (!fs.existsSync(signingConfigsPath)) {
console.error("File referenced by SERVO_OHOS_SIGNING_CONFIG does not exist!");
return;
}
const basePath = path.dirname(signingConfigsPath);
const signingConfigs = JSON.parse(fs.readFileSync(signingConfigsPath));
for (const config of signingConfigs) {
config.material.certpath = path.resolve(basePath, config.material.certpath);
config.material.profile = path.resolve(basePath, config.material.profile);
config.material.storeFile = path.resolve(basePath, config.material.storeFile);
}
buildProfileOpt['app']['signingConfigs'] = signingConfigs;
} else {
console.log('Signing config not found in enviroment. hvigor will fallback to build-profile.json5.')
}
// Set the obj object back to the context object to enable the build process and results.
appContext.setBuildProfileOpt(buildProfileOpt);
})
export default {
system: appTasks, /* Built-in plugin of Hvigor. It cannot be modified. */
plugins:[] /* Custom plugin to extend the functionality of Hvigor. */
}

View file

@ -0,0 +1,20 @@
{
"meta": {
"stableOrder": true
},
"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-IgF26ui+ZL2/5ITpAoHqtNbpdDOyoXTjK8TEyncETNyH3gzklKD9+ZPdsxEvNVRbigiptmisfugNBNFM3OdpeQ==",
"resolved": "https://cmc.centralrepo.rnd.huawei.com/artifactory/api/npm/product_npm/@ohos/hypium/-/@ohos/hypium-1.0.6.tgz",
"shasum": "c2042745b131325ccf3d2b7eb7f77306758a838b",
"registryType": "npm"
}
}
}

View file

@ -0,0 +1,13 @@
{
"modelVersion": "5.0.0",
"license": "Apache-2.0",
"devDependencies": {
"@ohos/hypium": "1.0.6"
},
"author": "",
"name": "servoshell",
"description": "Servo browser shell",
"main": "",
"version": "1.0.0",
"dependencies": {}
}