diff --git a/ArkWebKit/ArkWebClipboard/.gitignore b/ArkWebKit/ArkWebClipboard/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..d2ff20141ceed86d87c0ea5d99481973005bab2b
--- /dev/null
+++ b/ArkWebKit/ArkWebClipboard/.gitignore
@@ -0,0 +1,12 @@
+/node_modules
+/oh_modules
+/local.properties
+/.idea
+**/build
+/.hvigor
+.cxx
+/.clangd
+/.clang-format
+/.clang-tidy
+**/.test
+/.appanalyzer
\ No newline at end of file
diff --git a/ArkWebKit/ArkWebClipboard/AppScope/app.json5 b/ArkWebKit/ArkWebClipboard/AppScope/app.json5
new file mode 100644
index 0000000000000000000000000000000000000000..52a5b93f239400c0ee5a6aef2156a3c3ef0fdfcf
--- /dev/null
+++ b/ArkWebKit/ArkWebClipboard/AppScope/app.json5
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2025 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+{
+ "app": {
+ "bundleName": "com.samples.webclipboard",
+ "vendor": "example",
+ "versionCode": 1000000,
+ "versionName": "1.0.0",
+ "icon": "$media:layered_image",
+ "label": "$string:app_name"
+ }
+}
diff --git a/ArkWebKit/ArkWebClipboard/AppScope/resources/base/element/string.json b/ArkWebKit/ArkWebClipboard/AppScope/resources/base/element/string.json
new file mode 100644
index 0000000000000000000000000000000000000000..445db917e30fc9672e25879733c0c8020a1aeb1a
--- /dev/null
+++ b/ArkWebKit/ArkWebClipboard/AppScope/resources/base/element/string.json
@@ -0,0 +1,8 @@
+{
+ "string": [
+ {
+ "name": "app_name",
+ "value": "ArkWebClipboard"
+ }
+ ]
+}
diff --git a/ArkWebKit/ArkWebClipboard/AppScope/resources/base/media/background.png b/ArkWebKit/ArkWebClipboard/AppScope/resources/base/media/background.png
new file mode 100644
index 0000000000000000000000000000000000000000..923f2b3f27e915d6871871deea0420eb45ce102f
Binary files /dev/null and b/ArkWebKit/ArkWebClipboard/AppScope/resources/base/media/background.png differ
diff --git a/ArkWebKit/ArkWebClipboard/AppScope/resources/base/media/foreground.png b/ArkWebKit/ArkWebClipboard/AppScope/resources/base/media/foreground.png
new file mode 100644
index 0000000000000000000000000000000000000000..eb9427585b36d14b12477435b6419d1f07b3e0bb
Binary files /dev/null and b/ArkWebKit/ArkWebClipboard/AppScope/resources/base/media/foreground.png differ
diff --git a/ArkWebKit/ArkWebClipboard/AppScope/resources/base/media/layered_image.json b/ArkWebKit/ArkWebClipboard/AppScope/resources/base/media/layered_image.json
new file mode 100644
index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a
--- /dev/null
+++ b/ArkWebKit/ArkWebClipboard/AppScope/resources/base/media/layered_image.json
@@ -0,0 +1,7 @@
+{
+ "layered-image":
+ {
+ "background" : "$media:background",
+ "foreground" : "$media:foreground"
+ }
+}
\ No newline at end of file
diff --git a/ArkWebKit/ArkWebClipboard/README.md b/ArkWebKit/ArkWebClipboard/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..2687b949d9bd3d30e0de3ac4cc212f73ac3aa0f0
--- /dev/null
+++ b/ArkWebKit/ArkWebClipboard/README.md
@@ -0,0 +1,107 @@
+# 使用Web组件与系统剪贴板交互处理网页内容
+
+### 介绍
+
+1. 开发者能够通过Web组件和系统剪贴板进行交互,实现各种类型数据的复制和粘贴。支持通过[菜单](https://gitcode.com/openharmony/docs/blob/master/zh-cn/application-dev/web/web_menu.md)、键盘快捷键以及[W3C剪贴板接口](https://www.w3.org/TR/clipboard-apis/)对网页内容执行剪切、复制和粘贴操作。
+2. 本工程主要实现了对以下指南文档中[使用Web组件与系统剪贴板交互处理网页内容](https://gitcode.com/openharmony/docs/blob/master/zh-cn/application-dev/web/web-clipboard.md)示例代码片段的工程化,帮助开发者快速了解Web组件和系统剪贴板之间如何交互。
+
+### 通过W3C异步剪贴板接口与系统剪贴板交互
+
+#### 介绍
+
+[异步剪贴板接口(Async Clipboard API)](https://www.w3.org/TR/clipboard-apis/#async-clipboard-api)提供给网页开发者读写系统剪贴板的方法,这让Web应用程序可以实现剪切、复制和粘贴的功能。
+
+#### 效果预览
+
+| Clipboard API demo |
+|-----------------------------------------------------------|
+|
|
+
+##### 使用说明
+
+* 通过异步剪贴板接口read()和readText()方法访问系统剪贴板内容,需[申请访问剪贴板权限](https://gitcode.com/openharmony/docs/blob/master/zh-cn/application-dev/basic-services/pasteboard/get-pastedata-permission-guidelines.md):ohos.permission.READ_PASTEBOARD。
+* 使用writeText、write等API将内容写入系统剪贴板。使用readText、read等API从系统剪贴板获取文本内容
+
+#### 工程目录
+
+```
+├── entry
+│ └── src
+│ └── main
+│ ├── ets // ArkTS代码区
+│ │ ├── entryability
+│ │ │ └── EntryAbility.ets // 入口类
+│ │ ├── entrybackupability
+│ │ │ └── EntryBackupAbility.ets // 备份恢复框架
+│ │ └── pages
+│ │ └── Index.ets // 主页
+│ └── resources // 应用资源文件
+```
+
+### 通过W3C剪贴板事件接口与系统剪贴板交互
+
+#### 介绍
+
+[剪贴板事件(Clipboard Event)](https://www.w3.org/TR/clipboard-apis/#clipboard-events-and-interfaces)描述了与剪切板相关的cut、copy和paste事件。当用户执行剪切、复制或粘贴操作时,相应的事件将被触发。开发者可以通过监听这些事件,对系统剪贴板进行读写操作,或拦截默认行为,以更改复制或粘贴的结果。
+#### 效果预览
+
+| Clipboard Event监听示例 |
+|----------------------------------------------------------------|
+|
|
+
+##### 使用说明
+* 通过监听网页的复制、粘贴、剪切事件,获取到内容。
+* 使用navigator.clipboard 相关 API,访问剪贴板内容。
+
+
+#### 工程目录
+
+```
+├── entry2
+│ └── src
+│ └── main
+│ ├── ets // ArkTS代码区
+│ │ ├── entryability
+│ │ │ └── EntryAbility.ets // 入口类
+│ │ ├── entrybackupability
+│ │ │ └── EntryBackupAbility.ets // 备份恢复框架
+│ │ └── pages
+│ │ └── Index.ets // 主页
+│ └── resources // 应用资源文件
+```
+
+### 具体实现
+* 使用Web组件与系统剪贴板交互处理网页内容
+* 通过W3C异步剪贴板接口与系统剪贴板交互
+ * [异步剪贴板接口(Async Clipboard API)](https://www.w3.org/TR/clipboard-apis/#async-clipboard-api)提供给网页开发者读写系统剪贴板的方法。
+ * writeText:将文本内容写入系统剪贴板。write:将任意类型内容写入系统剪贴板。
+ * readText:从系统剪贴板读取文本内容。read():从系统剪贴板读取任意类型内容。
+* 通过W3C剪贴板事件接口与系统剪贴板交互
+ * [剪贴板事件(Clipboard Event)](https://www.w3.org/TR/clipboard-apis/#clipboard-events-and-interfaces)描述了与剪切板相关的cut、copy和paste事件。当用户执行剪切、复制或粘贴操作时,相应的事件将被触发。
+ * 通过addEventListener的方式监听copy、paste、cut事件,对系统剪贴板进行读写操作
+
+### 相关权限
+
+[ohos.permission.INTERNET](https://docs.openharmony.cn/pages/v6.0/zh-cn/application-dev/security/AccessToken/permissions-for-all.md#ohospermissioninternet)
+
+### 依赖
+
+不涉及。
+
+### 约束与限制
+
+1. 本示例仅支持标准系统上运行。
+2. 本示例支持API14版本SDK,SDK版本号(API Version 20 Release)。
+3. 本示例需要使用DevEco Studio 版本号(6.0.0Release)才可编译运行。
+
+### 下载
+
+如需单独下载本工程,执行如下命令:
+
+```
+git init
+git config core.sparsecheckout true
+echo code/DocsSample/ArkWeb/ArkWebClipboard > .git/info/sparse-checkout
+git remote add origin https://gitcode.com/openharmony/applications_app_samples.git
+git pull origin master
+```
\ No newline at end of file
diff --git a/ArkWebKit/ArkWebClipboard/build-profile.json5 b/ArkWebKit/ArkWebClipboard/build-profile.json5
new file mode 100644
index 0000000000000000000000000000000000000000..cdb0ee92784db908ecca9a70e401d494e38b677d
--- /dev/null
+++ b/ArkWebKit/ArkWebClipboard/build-profile.json5
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2025 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+{
+ "app": {
+ "signingConfigs": [
+ {
+ "name": "default",
+ "type": "HarmonyOS",
+ "material": {
+ "certpath": "C:\\Users\\wangrongfei.ICS-VTBAFCLMWDF\\.ohos\\config\\default_ArkWebClipboard_XRWg3QlnEtyzg2lvV9fxB0T52ZNsTs2OuJ6BzG3JAM8=.cer",
+ "keyAlias": "debugKey",
+ "keyPassword": "0000001B802819DC69D0ECB72C90A6761856BCEF2379DD1A524BAADD507B24B197DE36366DF8479C9C050F",
+ "profile": "C:\\Users\\wangrongfei.ICS-VTBAFCLMWDF\\.ohos\\config\\default_ArkWebClipboard_XRWg3QlnEtyzg2lvV9fxB0T52ZNsTs2OuJ6BzG3JAM8=.p7b",
+ "signAlg": "SHA256withECDSA",
+ "storeFile": "C:\\Users\\wangrongfei.ICS-VTBAFCLMWDF\\.ohos\\config\\default_ArkWebClipboard_XRWg3QlnEtyzg2lvV9fxB0T52ZNsTs2OuJ6BzG3JAM8=.p12",
+ "storePassword": "0000001B8314451DC893A12FCD06A9E50A09625231C90DACCBBCD869FBB13B1B44742538F72298B7CC6263"
+ }
+ }
+ ],
+ "products": [
+ {
+ "name": "default",
+ "signingConfig": "default",
+ "targetSdkVersion": "6.0.0(20)",
+ "compatibleSdkVersion": "6.0.0(20)",
+ "runtimeOS": "HarmonyOS",
+ "buildOption": {
+ "strictMode": {
+ "caseSensitiveCheck": true,
+ "useNormalizedOHMUrl": true
+ }
+ }
+ }
+ ],
+ "buildModeSet": [
+ {
+ "name": "debug",
+ },
+ {
+ "name": "release"
+ }
+ ]
+ },
+ "modules": [
+ {
+ "name": "entry",
+ "srcPath": "./entry",
+ "targets": [
+ {
+ "name": "default",
+ "applyToProducts": [
+ "default"
+ ]
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/ArkWebKit/ArkWebClipboard/code-linter.json5 b/ArkWebKit/ArkWebClipboard/code-linter.json5
new file mode 100644
index 0000000000000000000000000000000000000000..5c4682f8164874ec7e9cb8f99ff8b3228ffbc126
--- /dev/null
+++ b/ArkWebKit/ArkWebClipboard/code-linter.json5
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2025 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+{
+ "files": [
+ "**/*.ets"
+ ],
+ "ignore": [
+ "**/src/ohosTest/**/*",
+ "**/src/test/**/*",
+ "**/src/mock/**/*",
+ "**/node_modules/**/*",
+ "**/oh_modules/**/*",
+ "**/build/**/*",
+ "**/.preview/**/*"
+ ],
+ "ruleSet": [
+ "plugin:@performance/recommended",
+ "plugin:@typescript-eslint/recommended"
+ ],
+ "rules": {
+ "@security/no-unsafe-aes": "error",
+ "@security/no-unsafe-hash": "error",
+ "@security/no-unsafe-mac": "warn",
+ "@security/no-unsafe-dh": "error",
+ "@security/no-unsafe-dsa": "error",
+ "@security/no-unsafe-ecdsa": "error",
+ "@security/no-unsafe-rsa-encrypt": "error",
+ "@security/no-unsafe-rsa-sign": "error",
+ "@security/no-unsafe-rsa-key": "error",
+ "@security/no-unsafe-dsa-key": "error",
+ "@security/no-unsafe-dh-key": "error",
+ "@security/no-unsafe-3des": "error"
+ }
+}
\ No newline at end of file
diff --git a/ArkWebKit/ArkWebClipboard/entry/build-profile.json5 b/ArkWebKit/ArkWebClipboard/entry/build-profile.json5
new file mode 100644
index 0000000000000000000000000000000000000000..9016faf39f8a65cf648bae246a53575510fe8b9f
--- /dev/null
+++ b/ArkWebKit/ArkWebClipboard/entry/build-profile.json5
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2025 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+{
+ "apiType": "stageMode",
+ "buildOption": {
+ "resOptions": {
+ "copyCodeResource": {
+ "enable": false
+ }
+ }
+ },
+ "buildOptionSet": [
+ {
+ "name": "release",
+ "arkOptions": {
+ "obfuscation": {
+ "ruleOptions": {
+ "enable": false,
+ "files": [
+ "./obfuscation-rules.txt"
+ ]
+ }
+ }
+ }
+ },
+ ],
+ "targets": [
+ {
+ "name": "default"
+ },
+ {
+ "name": "ohosTest",
+ }
+ ]
+}
\ No newline at end of file
diff --git a/ArkWebKit/ArkWebClipboard/entry/hvigorfile.ts b/ArkWebKit/ArkWebClipboard/entry/hvigorfile.ts
new file mode 100644
index 0000000000000000000000000000000000000000..f8b117a17af3b2d7cb87a7680e29e2bb8ccd5b46
--- /dev/null
+++ b/ArkWebKit/ArkWebClipboard/entry/hvigorfile.ts
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2025 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+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. */
+}
\ No newline at end of file
diff --git a/ArkWebKit/ArkWebClipboard/entry/obfuscation-rules.txt b/ArkWebKit/ArkWebClipboard/entry/obfuscation-rules.txt
new file mode 100644
index 0000000000000000000000000000000000000000..272efb6ca3f240859091bbbfc7c5802d52793b0b
--- /dev/null
+++ b/ArkWebKit/ArkWebClipboard/entry/obfuscation-rules.txt
@@ -0,0 +1,23 @@
+# 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://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/source-obfuscation-V5
+
+# 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
+
+-enable-property-obfuscation
+-enable-toplevel-obfuscation
+-enable-filename-obfuscation
+-enable-export-obfuscation
\ No newline at end of file
diff --git a/ArkWebKit/ArkWebClipboard/entry/oh-package.json5 b/ArkWebKit/ArkWebClipboard/entry/oh-package.json5
new file mode 100644
index 0000000000000000000000000000000000000000..10cda399b0aec3099b257299a57d284393e4e55a
--- /dev/null
+++ b/ArkWebKit/ArkWebClipboard/entry/oh-package.json5
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2025 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+{
+ "name": "entry",
+ "version": "1.0.0",
+ "description": "Please describe the basic information.",
+ "main": "",
+ "author": "",
+ "license": "",
+ "dependencies": {}
+}
+
diff --git a/ArkWebKit/ArkWebClipboard/entry/src/main/ets/entryability/EntryAbility.ets b/ArkWebKit/ArkWebClipboard/entry/src/main/ets/entryability/EntryAbility.ets
new file mode 100644
index 0000000000000000000000000000000000000000..62f53acbc95e5be7985f8fb1fe2db591cea260bd
--- /dev/null
+++ b/ArkWebKit/ArkWebClipboard/entry/src/main/ets/entryability/EntryAbility.ets
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2025 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { AbilityConstant, ConfigurationConstant, UIAbility, Want } from '@kit.AbilityKit';
+import { hilog } from '@kit.PerformanceAnalysisKit';
+import { window } from '@kit.ArkUI';
+
+const DOMAIN = 0x0000;
+
+export default class EntryAbility extends UIAbility {
+ onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
+ try {
+ this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET);
+ } catch (err) {
+ hilog.error(DOMAIN, 'testTag', 'Failed to set colorMode. Cause: %{public}s', JSON.stringify(err));
+ }
+ hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onCreate');
+ }
+
+ onDestroy(): void {
+ hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onDestroy');
+ }
+
+ onWindowStageCreate(windowStage: window.WindowStage): void {
+ // Main window is created, set main page for this ability
+ hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageCreate');
+
+ windowStage.loadContent('pages/Index', (err) => {
+ if (err.code) {
+ hilog.error(DOMAIN, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err));
+ return;
+ }
+ hilog.info(DOMAIN, 'testTag', 'Succeeded in loading the content.');
+ });
+ }
+
+ onWindowStageDestroy(): void {
+ // Main window is destroyed, release UI related resources
+ hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageDestroy');
+ }
+
+ onForeground(): void {
+ // Ability has brought to foreground
+ hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onForeground');
+ }
+
+ onBackground(): void {
+ // Ability has back to background
+ hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onBackground');
+ }
+}
\ No newline at end of file
diff --git a/ArkWebKit/ArkWebClipboard/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets b/ArkWebKit/ArkWebClipboard/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets
new file mode 100644
index 0000000000000000000000000000000000000000..0a97e21bd7a15599af76a806695860ff1eb0ebfe
--- /dev/null
+++ b/ArkWebKit/ArkWebClipboard/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2025 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { hilog } from '@kit.PerformanceAnalysisKit';
+import { BackupExtensionAbility, BundleVersion } from '@kit.CoreFileKit';
+
+const DOMAIN = 0x0000;
+
+export default class EntryBackupAbility extends BackupExtensionAbility {
+ async onBackup() {
+ hilog.info(DOMAIN, 'testTag', 'onBackup ok');
+ await Promise.resolve();
+ }
+
+ async onRestore(bundleVersion: BundleVersion) {
+ hilog.info(DOMAIN, 'testTag', 'onRestore ok %{public}s', JSON.stringify(bundleVersion));
+ await Promise.resolve();
+ }
+}
\ No newline at end of file
diff --git a/ArkWebKit/ArkWebClipboard/entry/src/main/ets/pages/Index.ets b/ArkWebKit/ArkWebClipboard/entry/src/main/ets/pages/Index.ets
new file mode 100644
index 0000000000000000000000000000000000000000..06d96634f37d8fb77be40983d6a4ffdbc211f9b4
--- /dev/null
+++ b/ArkWebKit/ArkWebClipboard/entry/src/main/ets/pages/Index.ets
@@ -0,0 +1,63 @@
+/*
+* Copyright (c) 2025 Huawei Device Co., Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+import { BusinessError } from '@kit.BasicServicesKit';
+import { common } from '@kit.AbilityKit';
+import hilog from '@ohos.hilog';
+
+const TAG = '[Sample_WebClipboard]'
+const DOMAIN = 0xF811
+const BUNDLE = 'WebClipboard_'
+//Column space
+const COLUMN_SPACE: Length = 10;
+
+@Entry
+@Component
+struct Index {
+ build() {
+ Column({ space: COLUMN_SPACE }) {
+ Button('clipboard')
+ .onClick(() => {
+ this.getUIContext().getRouter().pushUrl({
+ url: 'pages/WebClipboard',
+ })
+ .catch((error: BusinessError) => {
+ hilog.error(DOMAIN, TAG, BUNDLE + `pushUrl failed, code is ${error.code}, message is ${error.message}`)
+ })
+ })
+ Button('clipboard event')
+ .onClick(() => {
+ this.getUIContext().getRouter().pushUrl({
+ url: 'pages/WebClipboardEvent',
+ })
+ .catch((error: BusinessError) => {
+ hilog.error(DOMAIN, TAG, BUNDLE + `pushUrl failed, code is ${error.code}, message is ${error.message}`);
+ })
+ })
+
+ Button('copy Options')
+ .onClick(() => {
+ this.getUIContext().getRouter().pushUrl({
+ url: 'pages/WebCopyOptions',
+ })
+ .catch((error: BusinessError) => {
+ hilog.error(DOMAIN, TAG, BUNDLE + `pushUrl failed, code is ${error.code}, message is ${error.message}`);
+ })
+ })
+
+ }.height('100%')
+ .width('100%')
+ }
+}
\ No newline at end of file
diff --git a/ArkWebKit/ArkWebClipboard/entry/src/main/ets/pages/WebClipboard.ets b/ArkWebKit/ArkWebClipboard/entry/src/main/ets/pages/WebClipboard.ets
new file mode 100644
index 0000000000000000000000000000000000000000..49f5d7973af062cb94bf698c2cc51ab6749a872f
--- /dev/null
+++ b/ArkWebKit/ArkWebClipboard/entry/src/main/ets/pages/WebClipboard.ets
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2025 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// [Start web_clipboard_content]
+import { webview } from '@kit.ArkWeb';
+
+@Entry
+@Component
+struct WebComponent {
+ controller: webview.WebviewController = new webview.WebviewController();
+
+ build() {
+ Column() {
+ Web({ src: $rawfile('clipboard.html'), controller: this.controller })
+ }
+ }
+}
+// [End web_clipboard_content]
diff --git a/ArkWebKit/ArkWebClipboard/entry/src/main/ets/pages/WebClipboardEvent.ets b/ArkWebKit/ArkWebClipboard/entry/src/main/ets/pages/WebClipboardEvent.ets
new file mode 100644
index 0000000000000000000000000000000000000000..324fde0b8e74eee017ca5dff64c8a59e2c797dd2
--- /dev/null
+++ b/ArkWebKit/ArkWebClipboard/entry/src/main/ets/pages/WebClipboardEvent.ets
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2025 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// [Start web_clipboard_event]
+import { webview } from '@kit.ArkWeb';
+
+@Entry
+@Component
+struct WebComponent {
+ controller: webview.WebviewController = new webview.WebviewController();
+
+ build() {
+ Column() {
+ Web({ src: $rawfile('clipboard_event.html'), controller: this.controller })
+ }
+ }
+}
+// [End web_clipboard_event]
diff --git a/ArkWebKit/ArkWebClipboard/entry/src/main/ets/pages/WebCopyOptions.ets b/ArkWebKit/ArkWebClipboard/entry/src/main/ets/pages/WebCopyOptions.ets
new file mode 100644
index 0000000000000000000000000000000000000000..d3d03d684fe93d892dd2d990b4a6d06ba35050cd
--- /dev/null
+++ b/ArkWebKit/ArkWebClipboard/entry/src/main/ets/pages/WebCopyOptions.ets
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2025 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// [Start web_clipboard_copyOptions]
+import { webview } from '@kit.ArkWeb';
+
+@Entry
+@Component
+struct WebComponent {
+ controller: webview.WebviewController = new webview.WebviewController();
+ @State copyOption: CopyOptions = CopyOptions.LocalDevice;
+
+ build() {
+ Column() {
+ Web({ src: $rawfile('copyOptions.html'), controller: this.controller })
+ .copyOptions(this.copyOption)
+ }
+ }
+}
+// [End web_clipboard_copyOptions]
diff --git a/ArkWebKit/ArkWebClipboard/entry/src/main/module.json5 b/ArkWebKit/ArkWebClipboard/entry/src/main/module.json5
new file mode 100644
index 0000000000000000000000000000000000000000..bf2232a36fceb6a9da8e4cd4024843d0c2f0d350
--- /dev/null
+++ b/ArkWebKit/ArkWebClipboard/entry/src/main/module.json5
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2025 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// [Start web_clipboard_permissions]
+{
+ "module": {
+ // [StartExclude web_clipboard_permissions]
+ "name": "entry",
+ "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:layered_image",
+ "label": "$string:EntryAbility_label",
+ "startWindowIcon": "$media:startIcon",
+ "startWindowBackground": "$color:start_window_background",
+ "exported": true,
+ "skills": [
+ {
+ "entities": [
+ "entity.system.home"
+ ],
+ "actions": [
+ "ohos.want.action.home"
+ ]
+ }
+ ]
+ }
+ ],
+ "extensionAbilities": [
+ {
+ "name": "EntryBackupAbility",
+ "srcEntry": "./ets/entrybackupability/EntryBackupAbility.ets",
+ "type": "backup",
+ "exported": false,
+ "metadata": [
+ {
+ "name": "ohos.extension.backup",
+ "resource": "$profile:backup_config"
+ }
+ ],
+ }
+ ],
+ // [EndExclude web_clipboard_permissions]
+ "requestPermissions": [
+ {
+ "name" : "ohos.permission.READ_PASTEBOARD",
+ "reason": "$string:module_desc",
+ "usedScene": {
+ "abilities": [
+ "FormAbility"
+ ],
+ "when":"inuse"
+ }
+ }
+ ]
+ }
+}
+// [End web_clipboard_permissions]
diff --git a/ArkWebKit/ArkWebClipboard/entry/src/main/resources/base/element/color.json b/ArkWebKit/ArkWebClipboard/entry/src/main/resources/base/element/color.json
new file mode 100644
index 0000000000000000000000000000000000000000..3c712962da3c2751c2b9ddb53559afcbd2b54a02
--- /dev/null
+++ b/ArkWebKit/ArkWebClipboard/entry/src/main/resources/base/element/color.json
@@ -0,0 +1,8 @@
+{
+ "color": [
+ {
+ "name": "start_window_background",
+ "value": "#FFFFFF"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/ArkWebKit/ArkWebClipboard/entry/src/main/resources/base/element/float.json b/ArkWebKit/ArkWebClipboard/entry/src/main/resources/base/element/float.json
new file mode 100644
index 0000000000000000000000000000000000000000..33ea22304f9b1485b5f22d811023701b5d4e35b6
--- /dev/null
+++ b/ArkWebKit/ArkWebClipboard/entry/src/main/resources/base/element/float.json
@@ -0,0 +1,8 @@
+{
+ "float": [
+ {
+ "name": "page_text_font_size",
+ "value": "50fp"
+ }
+ ]
+}
diff --git a/ArkWebKit/ArkWebClipboard/entry/src/main/resources/base/element/string.json b/ArkWebKit/ArkWebClipboard/entry/src/main/resources/base/element/string.json
new file mode 100644
index 0000000000000000000000000000000000000000..f94595515a99e0c828807e243494f57f09251930
--- /dev/null
+++ b/ArkWebKit/ArkWebClipboard/entry/src/main/resources/base/element/string.json
@@ -0,0 +1,16 @@
+{
+ "string": [
+ {
+ "name": "module_desc",
+ "value": "module description"
+ },
+ {
+ "name": "EntryAbility_desc",
+ "value": "description"
+ },
+ {
+ "name": "EntryAbility_label",
+ "value": "label"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/ArkWebKit/ArkWebClipboard/entry/src/main/resources/base/media/background.png b/ArkWebKit/ArkWebClipboard/entry/src/main/resources/base/media/background.png
new file mode 100644
index 0000000000000000000000000000000000000000..923f2b3f27e915d6871871deea0420eb45ce102f
Binary files /dev/null and b/ArkWebKit/ArkWebClipboard/entry/src/main/resources/base/media/background.png differ
diff --git a/ArkWebKit/ArkWebClipboard/entry/src/main/resources/base/media/foreground.png b/ArkWebKit/ArkWebClipboard/entry/src/main/resources/base/media/foreground.png
new file mode 100644
index 0000000000000000000000000000000000000000..97014d3e10e5ff511409c378cd4255713aecd85f
Binary files /dev/null and b/ArkWebKit/ArkWebClipboard/entry/src/main/resources/base/media/foreground.png differ
diff --git a/ArkWebKit/ArkWebClipboard/entry/src/main/resources/base/media/layered_image.json b/ArkWebKit/ArkWebClipboard/entry/src/main/resources/base/media/layered_image.json
new file mode 100644
index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a
--- /dev/null
+++ b/ArkWebKit/ArkWebClipboard/entry/src/main/resources/base/media/layered_image.json
@@ -0,0 +1,7 @@
+{
+ "layered-image":
+ {
+ "background" : "$media:background",
+ "foreground" : "$media:foreground"
+ }
+}
\ No newline at end of file
diff --git a/ArkWebKit/ArkWebClipboard/entry/src/main/resources/base/media/startIcon.png b/ArkWebKit/ArkWebClipboard/entry/src/main/resources/base/media/startIcon.png
new file mode 100644
index 0000000000000000000000000000000000000000..205ad8b5a8a42e8762fbe4899b8e5e31ce822b8b
Binary files /dev/null and b/ArkWebKit/ArkWebClipboard/entry/src/main/resources/base/media/startIcon.png differ
diff --git a/ArkWebKit/ArkWebClipboard/entry/src/main/resources/base/profile/backup_config.json b/ArkWebKit/ArkWebClipboard/entry/src/main/resources/base/profile/backup_config.json
new file mode 100644
index 0000000000000000000000000000000000000000..78f40ae7c494d71e2482278f359ec790ca73471a
--- /dev/null
+++ b/ArkWebKit/ArkWebClipboard/entry/src/main/resources/base/profile/backup_config.json
@@ -0,0 +1,3 @@
+{
+ "allowToBackupRestore": true
+}
\ No newline at end of file
diff --git a/ArkWebKit/ArkWebClipboard/entry/src/main/resources/base/profile/main_pages.json b/ArkWebKit/ArkWebClipboard/entry/src/main/resources/base/profile/main_pages.json
new file mode 100644
index 0000000000000000000000000000000000000000..736d40597dfae42e8bb635f5f2fd79ed6a1d309a
--- /dev/null
+++ b/ArkWebKit/ArkWebClipboard/entry/src/main/resources/base/profile/main_pages.json
@@ -0,0 +1,8 @@
+{
+ "src": [
+ "pages/Index",
+ "pages/WebClipboard",
+ "pages/WebClipboardEvent",
+ "pages/WebCopyOptions"
+ ]
+}
diff --git a/ArkWebKit/ArkWebClipboard/entry/src/main/resources/dark/element/color.json b/ArkWebKit/ArkWebClipboard/entry/src/main/resources/dark/element/color.json
new file mode 100644
index 0000000000000000000000000000000000000000..79b11c2747aec33e710fd3a7b2b3c94dd9965499
--- /dev/null
+++ b/ArkWebKit/ArkWebClipboard/entry/src/main/resources/dark/element/color.json
@@ -0,0 +1,8 @@
+{
+ "color": [
+ {
+ "name": "start_window_background",
+ "value": "#000000"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/ArkWebKit/ArkWebClipboard/entry/src/main/resources/rawfile/clipboard.html b/ArkWebKit/ArkWebClipboard/entry/src/main/resources/rawfile/clipboard.html
new file mode 100644
index 0000000000000000000000000000000000000000..25186b819703006c41cfc8767ccbb8baeabec14f
--- /dev/null
+++ b/ArkWebKit/ArkWebClipboard/entry/src/main/resources/rawfile/clipboard.html
@@ -0,0 +1,83 @@
+
+
+
+
没有复制或粘贴内容。
+
|
+
+##### 使用说明
+
+* 通过onCreateMenu方法自定义菜单项,通过操作Array
|
+
+##### 使用说明
+
+* Menu组件作为弹出的菜单,包含所有菜单项行为与样式。
+* 使用bindPopup方法将Menu组件与Web组件绑定。当上下文菜单弹出时,将显示创建的Menu组件。
+* 在onContextMenuShow回调中获取上下文菜单事件信息onContextMenuShowEvent。其中param为WebContextMenuParam类型,包含点击位置对应HTML元素信息和位置信息,result为WebContextMenuResult类型,提供常见的菜单能力。
+
+
+#### 工程目录
+
+```
+├── entry2
+│ └── src
+│ └── main
+│ ├── ets // ArkTS代码区
+│ │ ├── entryability
+│ │ │ └── Entry2Ability.ets // 入口类
+│ │ ├── entrybackupability
+│ │ │ └── EntryBackupAbility.ets // 备份恢复框架
+│ │ └── pages
+│ │ └── Index.ets // 主页
+│ └── resources // 应用资源文件
+```
+
+### 自定义菜单
+
+#### 介绍
+
+自定义菜单赋予开发者调整菜单触发时机与视觉展现的能力,使应用能够依据用户操作场景动态匹配功能入口,简化开发流程中的界面适配工作,同时使应用交互更符合用户直觉。应用可通过bindSelectionMenu接口,实现自定义菜单。目前已额外支持通过长按图片和链接响应自定义菜单。
+
+#### 效果预览
+
+|自定义菜单 |
+|--------------------------------------------------------------------|
+|
|
+
+##### 使用说明
+* 创建Menu组件作为菜单弹窗。
+* 通过Web组件的bindSelectionMenu方法绑定MenuBuilder菜单弹窗。将WebElementType设置为WebElementType.IMAGE,responseType设置为WebResponseType.LONG_PRESS,表示长按图片时弹出菜单。在options中定义菜单显示回调onAppear、菜单消失回调onDisappear、预览窗口preview和菜单类型menuType。
+
+#### 工程目录
+```
+├── entry3
+│ └── src
+│ └── main
+│ ├── ets // ArkTS代码区
+│ │ ├── entryability
+│ │ │ └── Entry3Ability.ets // 入口类
+│ │ ├── entrybackupability
+│ │ │ └── EntryBackupAbility.ets // 备份恢复框架
+│ │ └── pages
+│ │ └── Index.ets // 主页
+│ └── resources // 应用资源文件
+```
+
+### Web菜单保存图片
+
+#### 介绍
+
+使用安全组件SaveButton保存web图片到图库。
+
+#### 效果预览
+
+|Web菜单保存图片 |
+|--------------------------------------------------------------------|
+|
|
+
+##### 使用说明
+* 创建MenuBuilder组件作为菜单弹窗,使用[SaveButton](https://gitcode.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis-arkui/arkui-ts/ts-security-components-savebutton.md)组件实现图片保存,通过bindContextMenu将MenuBuilder与Web绑定。
+* 在onContextMenuShow中获取图片url,通过copyLocalPicToDir或copyUrlPicToDir将图片保存至应用沙箱。
+* 通过photoAccessHelper将应用沙箱中的图片保存至图库。
+
+#### 工程目录
+```
+├── entry5
+│ └── src
+│ └── main
+│ ├── ets // ArkTS代码区
+│ │ ├── entryability
+│ │ │ └── Entry5Ability.ets // 入口类
+│ │ ├── entrybackupability
+│ │ │ └── EntryBackupAbility.ets // 备份恢复框架
+│ │ └── pages
+│ │ └── Index.ets // 主页
+│ └── resources // 应用资源文件
+```
+### Web菜单获取选中文本
+
+#### 介绍
+
+Web组件的editMenuOptions接口中没有提供获取选中文本的方式。开发者可通过javaScriptProxy获取到JavaScript的选中文本,实现自定义菜单的逻辑。
+#### 效果预览
+
+|Web菜单获取选中文本 |
+|----------------------------------------------------------------|
+|
|
+
+##### 使用说明
+* 创建SelectClass类,通过javaScriptProxy将SelectClass对象注册到Web组件中。
+* 在Html侧注册选区变更监听器,在选区变更时通过SelectClass对象将选区设置到ArkTS侧。
+
+#### 工程目录
+```
+├── entry6
+│ └── src
+│ └── main
+│ ├── ets // ArkTS代码区
+│ │ ├── entryability
+│ │ │ └── Entry6Ability.ets // 入口类
+│ │ ├── entrybackupability
+│ │ │ └── EntryBackupAbility.ets // 备份恢复框架
+│ │ └── pages
+│ │ └── Index.ets // 主页
+│ └── resources // 应用资源文件
+```
+
+### Web菜单识别图片二维码
+
+#### 介绍
+
+在二维码跳转页面或者付款场景中,开发者可通过实现上下文菜单,获取到onContextMenuShow接口中的二维码图片信息进行处理,提供给用户扫描二维码入口。
+
+#### 效果预览
+
+|Web菜单识别图片二维码 |
+|--------------------------------------------------------------------|
+|
|
+
+##### 使用说明
+* 创建MenuBuilder组件作为菜单弹窗,通过bindContextMenu将MenuBuilder与Web绑定。
+* 在onContextMenuShow中获取图片url,通过copyLocalPicToDir或copyUrlPicToDir将图片保存至应用沙箱。
+* 通过detectBarcode.decode解析保存在沙箱中的图片,获取到结果。
+
+#### 工程目录
+```
+├── entry7
+│ └── src
+│ └── main
+│ ├── ets // ArkTS代码区
+│ │ ├── entryability
+│ │ │ └── Entry7Ability.ets // 入口类
+│ │ ├── entrybackupability
+│ │ │ └── EntryBackupAbility.ets // 备份恢复框架
+│ │ └── pages
+│ │ └── Index.ets // 主页
+│ └── resources // 应用资源文件
+```
+
+### 具体实现
+* 使用Web组件菜单处理网页内容
+* 文本选中菜单实现:自定义菜单项与点击逻辑
+ * 通过 editMenuOptions 接口自定义文本选中时弹出的菜单,支持增减菜单项、控制系统默认行为。
+* 上下文菜单实现:绑定自定义弹窗与元素交互
+ * 针对超链接、图片等元素,通过 bindPopup 绑定自定义 Menu 组件,实现右键 / 长按触发的上下文菜单。
+* 自定义菜单实现:按元素类型绑定长按菜单(图片 / 链接)
+ * 通过 bindSelectionMenu 接口,为特定元素(图片 / 超链接)绑定专属长按菜单,支持预览窗口与菜单生命周期控制。
+* 菜单保存图片实现:沙箱暂存 + 图库持久化
+ * 通过上下文菜单结合文件操作、图库接口,实现 Web 组件中图片的保存功能。
+* 菜单获取选中文本实现:JS 与 ArkTS 通信
+ * 利用 javaScriptProxy 建立 Web 侧 JS 与 ArkTS 侧的通信,解决 editMenuOptions 无法直接获取选中文本的问题。
+* 菜单识别图片二维码实现:长按触发 + 图片解析
+ * 通过上下文菜单结合图片处理、二维码解析接口,实现 Web 组件中图片二维码的识
+### 相关权限
+
+不涉及
+
+### 依赖
+
+不涉及。
+
+### 约束与限制
+
+1. 本示例仅支持标准系统上运行。
+2. 本示例支持API14版本SDK,SDK版本号(API Version 20 Release)。
+3. 本示例需要使用DevEco Studio 版本号(6.0.0Release)才可编译运行。
+
+### 下载
+
+如需单独下载本工程,执行如下命令:
+
+```
+git init
+git config core.sparsecheckout true
+echo code/DocsSample/ArkWeb/ArkWebMenu > .git/info/sparse-checkout
+git remote add origin https://gitcode.com/openharmony/applications_app_samples.git
+git pull origin master
+```
\ No newline at end of file
diff --git a/ArkWebKit/ArkWebMenu/build-profile.json5 b/ArkWebKit/ArkWebMenu/build-profile.json5
new file mode 100644
index 0000000000000000000000000000000000000000..70fc5f86211a744ec7361750f6a908d602dc32f8
--- /dev/null
+++ b/ArkWebKit/ArkWebMenu/build-profile.json5
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2025 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+{
+ "app": {
+ "signingConfigs": [
+ {
+ "name": "default",
+ "type": "HarmonyOS",
+ "material": {
+ "certpath": "C:\\Users\\wangrongfei.ICS-VTBAFCLMWDF\\.ohos\\config\\default_ArkWebMenu_mN1lMyhK4or8rqJmJzZvt0CbnulWUSLLyCZjJsM3rlw=.cer",
+ "keyAlias": "debugKey",
+ "keyPassword": "0000001BA6AF5182E25A93202A2142E9736634290FDA501A303E00AC8607BC4242688724B061EECB8C6052",
+ "profile": "C:\\Users\\wangrongfei.ICS-VTBAFCLMWDF\\.ohos\\config\\default_ArkWebMenu_mN1lMyhK4or8rqJmJzZvt0CbnulWUSLLyCZjJsM3rlw=.p7b",
+ "signAlg": "SHA256withECDSA",
+ "storeFile": "C:\\Users\\wangrongfei.ICS-VTBAFCLMWDF\\.ohos\\config\\default_ArkWebMenu_mN1lMyhK4or8rqJmJzZvt0CbnulWUSLLyCZjJsM3rlw=.p12",
+ "storePassword": "0000001B3DAF6136BEDAE121DB8581EB341431D522D7D21282DE76B8159625CA00702B1088D4263D0CC7CB"
+ }
+ }
+ ],
+ "products": [
+ {
+ "name": "default",
+ "signingConfig": "default",
+ "targetSdkVersion": "6.0.0(20)",
+ "compatibleSdkVersion": "6.0.0(20)",
+ "runtimeOS": "HarmonyOS",
+ "buildOption": {
+ "strictMode": {
+ "caseSensitiveCheck": true,
+ "useNormalizedOHMUrl": true
+ }
+ }
+ }
+ ],
+ "buildModeSet": [
+ {
+ "name": "debug",
+ },
+ {
+ "name": "release"
+ }
+ ]
+ },
+ "modules": [
+ {
+ "name": "entry",
+ "srcPath": "./entry",
+ "targets": [
+ {
+ "name": "default",
+ "applyToProducts": [
+ "default"
+ ]
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/ArkWebKit/ArkWebMenu/code-linter.json5 b/ArkWebKit/ArkWebMenu/code-linter.json5
new file mode 100644
index 0000000000000000000000000000000000000000..5c4682f8164874ec7e9cb8f99ff8b3228ffbc126
--- /dev/null
+++ b/ArkWebKit/ArkWebMenu/code-linter.json5
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2025 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+{
+ "files": [
+ "**/*.ets"
+ ],
+ "ignore": [
+ "**/src/ohosTest/**/*",
+ "**/src/test/**/*",
+ "**/src/mock/**/*",
+ "**/node_modules/**/*",
+ "**/oh_modules/**/*",
+ "**/build/**/*",
+ "**/.preview/**/*"
+ ],
+ "ruleSet": [
+ "plugin:@performance/recommended",
+ "plugin:@typescript-eslint/recommended"
+ ],
+ "rules": {
+ "@security/no-unsafe-aes": "error",
+ "@security/no-unsafe-hash": "error",
+ "@security/no-unsafe-mac": "warn",
+ "@security/no-unsafe-dh": "error",
+ "@security/no-unsafe-dsa": "error",
+ "@security/no-unsafe-ecdsa": "error",
+ "@security/no-unsafe-rsa-encrypt": "error",
+ "@security/no-unsafe-rsa-sign": "error",
+ "@security/no-unsafe-rsa-key": "error",
+ "@security/no-unsafe-dsa-key": "error",
+ "@security/no-unsafe-dh-key": "error",
+ "@security/no-unsafe-3des": "error"
+ }
+}
\ No newline at end of file
diff --git a/ArkWebKit/ArkWebMenu/entry/build-profile.json5 b/ArkWebKit/ArkWebMenu/entry/build-profile.json5
new file mode 100644
index 0000000000000000000000000000000000000000..9016faf39f8a65cf648bae246a53575510fe8b9f
--- /dev/null
+++ b/ArkWebKit/ArkWebMenu/entry/build-profile.json5
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2025 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+{
+ "apiType": "stageMode",
+ "buildOption": {
+ "resOptions": {
+ "copyCodeResource": {
+ "enable": false
+ }
+ }
+ },
+ "buildOptionSet": [
+ {
+ "name": "release",
+ "arkOptions": {
+ "obfuscation": {
+ "ruleOptions": {
+ "enable": false,
+ "files": [
+ "./obfuscation-rules.txt"
+ ]
+ }
+ }
+ }
+ },
+ ],
+ "targets": [
+ {
+ "name": "default"
+ },
+ {
+ "name": "ohosTest",
+ }
+ ]
+}
\ No newline at end of file
diff --git a/ArkWebKit/ArkWebMenu/entry/hvigorfile.ts b/ArkWebKit/ArkWebMenu/entry/hvigorfile.ts
new file mode 100644
index 0000000000000000000000000000000000000000..f8b117a17af3b2d7cb87a7680e29e2bb8ccd5b46
--- /dev/null
+++ b/ArkWebKit/ArkWebMenu/entry/hvigorfile.ts
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2025 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+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. */
+}
\ No newline at end of file
diff --git a/ArkWebKit/ArkWebMenu/entry/obfuscation-rules.txt b/ArkWebKit/ArkWebMenu/entry/obfuscation-rules.txt
new file mode 100644
index 0000000000000000000000000000000000000000..272efb6ca3f240859091bbbfc7c5802d52793b0b
--- /dev/null
+++ b/ArkWebKit/ArkWebMenu/entry/obfuscation-rules.txt
@@ -0,0 +1,23 @@
+# 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://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/source-obfuscation-V5
+
+# 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
+
+-enable-property-obfuscation
+-enable-toplevel-obfuscation
+-enable-filename-obfuscation
+-enable-export-obfuscation
\ No newline at end of file
diff --git a/ArkWebKit/ArkWebMenu/entry/oh-package.json5 b/ArkWebKit/ArkWebMenu/entry/oh-package.json5
new file mode 100644
index 0000000000000000000000000000000000000000..10cda399b0aec3099b257299a57d284393e4e55a
--- /dev/null
+++ b/ArkWebKit/ArkWebMenu/entry/oh-package.json5
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2025 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+{
+ "name": "entry",
+ "version": "1.0.0",
+ "description": "Please describe the basic information.",
+ "main": "",
+ "author": "",
+ "license": "",
+ "dependencies": {}
+}
+
diff --git a/ArkWebKit/ArkWebMenu/entry/src/main/ets/entryability/EntryAbility.ets b/ArkWebKit/ArkWebMenu/entry/src/main/ets/entryability/EntryAbility.ets
new file mode 100644
index 0000000000000000000000000000000000000000..98182799de1294d4c21194646a0c30eff08aea33
--- /dev/null
+++ b/ArkWebKit/ArkWebMenu/entry/src/main/ets/entryability/EntryAbility.ets
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2025 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { AbilityConstant, ConfigurationConstant, UIAbility, Want } from '@kit.AbilityKit';
+import { hilog } from '@kit.PerformanceAnalysisKit';
+import { window } from '@kit.ArkUI';
+
+const DOMAIN = 0x0000;
+
+export default class EntryAbility extends UIAbility {
+ onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
+ try {
+ this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET);
+ } catch (err) {
+ hilog.error(DOMAIN, 'testTag', 'Failed to set colorMode. Cause: %{public}s', JSON.stringify(err));
+ }
+ hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onCreate');
+ }
+
+ onDestroy(): void {
+ hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onDestroy');
+ }
+
+ onWindowStageCreate(windowStage: window.WindowStage): void {
+ // Main window is created, set main page for this ability
+ hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageCreate');
+
+ windowStage.loadContent('pages/Index', (err) => {
+ if (err.code) {
+ hilog.error(DOMAIN, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err));
+ return;
+ }
+ hilog.info(DOMAIN, 'testTag', 'Succeeded in loading the content.');
+ });
+ }
+
+ onWindowStageDestroy(): void {
+ // Main window is destroyed, release UI related resources
+ hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageDestroy');
+ }
+
+ onForeground(): void {
+ // Ability has brought to foreground
+ hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onForeground');
+ }
+
+ onBackground(): void {
+ // Ability has back to background
+ hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onBackground');
+ }
+}
\ No newline at end of file
diff --git a/ArkWebKit/ArkWebMenu/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets b/ArkWebKit/ArkWebMenu/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets
new file mode 100644
index 0000000000000000000000000000000000000000..4ce6449f0e91914e73d4502c9f2e8e9a395ea4b1
--- /dev/null
+++ b/ArkWebKit/ArkWebMenu/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2025 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { hilog } from '@kit.PerformanceAnalysisKit';
+import { BackupExtensionAbility, BundleVersion } from '@kit.CoreFileKit';
+
+const DOMAIN = 0x0000;
+
+export default class EntryBackupAbility extends BackupExtensionAbility {
+ async onBackup() {
+ hilog.info(DOMAIN, 'testTag', 'onBackup ok');
+ await Promise.resolve();
+ }
+
+ async onRestore(bundleVersion: BundleVersion) {
+ hilog.info(DOMAIN, 'testTag', 'onRestore ok %{public}s', JSON.stringify(bundleVersion));
+ await Promise.resolve();
+ }
+}
\ No newline at end of file
diff --git a/ArkWebKit/ArkWebMenu/entry/src/main/ets/pages/Index.ets b/ArkWebKit/ArkWebMenu/entry/src/main/ets/pages/Index.ets
new file mode 100644
index 0000000000000000000000000000000000000000..8261d4161a29bdf3b9ba471a201d3eaeaf4bfe0c
--- /dev/null
+++ b/ArkWebKit/ArkWebMenu/entry/src/main/ets/pages/Index.ets
@@ -0,0 +1,111 @@
+/*
+* Copyright (c) 2025 Huawei Device Co., Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+import { BusinessError } from '@kit.BasicServicesKit';
+import { common } from '@kit.AbilityKit';
+import hilog from '@ohos.hilog';
+
+const TAG = '[Sample_WebMenu]'
+const DOMAIN = 0xF811
+const BUNDLE = 'WebMenu_'
+//Column space
+const COLUMN_SPACE: Length = 10;
+@Entry
+@Component
+struct Index {
+ build() {
+ Column({ space: COLUMN_SPACE }) {
+ Button('textMenuItem')
+ .onClick(() => {
+ this.getUIContext().getRouter().pushUrl({
+ url: 'pages/WebTextMenuItem',
+ })
+ .catch((error: BusinessError) => {
+ hilog.error(DOMAIN, TAG, BUNDLE + `pushUrl failed, code is ${error.code}, message is ${error.message}`)
+ })
+ })
+ Button('contextMenu')
+ .onClick(() => {
+ this.getUIContext().getRouter().pushUrl({
+ url: 'pages/WebContextMenu',
+ })
+ .catch((error: BusinessError) => {
+ hilog.error(DOMAIN, TAG, BUNDLE + `pushUrl failed, code is ${error.code}, message is ${error.message}`);
+ })
+ })
+
+ Button('bindSelectionMenu')
+ .onClick(() => {
+ this.getUIContext().getRouter().pushUrl({
+ url: 'pages/WebBindSelectionMenu',
+ })
+ .catch((error: BusinessError) => {
+ hilog.error(DOMAIN, TAG, BUNDLE + `pushUrl failed, code is ${error.code}, message is ${error.message}`);
+ })
+ })
+
+ Button('previewBuilder')
+ .onClick(() => {
+ this.getUIContext().getRouter().pushUrl({
+ url: 'pages/WebPreviewBuilder',
+ })
+ .catch((error: BusinessError) => {
+ hilog.error(DOMAIN, TAG, BUNDLE + `pushUrl failed, code is ${error.code}, message is ${error.message}`);
+ })
+ })
+
+ Button('saveImage')
+ .onClick(() => {
+ this.getUIContext().getRouter().pushUrl({
+ url: 'pages/WebSaveImage',
+ })
+ .catch((error: BusinessError) => {
+ hilog.error(DOMAIN, TAG, BUNDLE + `pushUrl failed, code is ${error.code}, message is ${error.message}`);
+ })
+ })
+
+ Button('editMenuOptions')
+ .onClick(() => {
+ this.getUIContext().getRouter().pushUrl({
+ url: 'pages/WebEditMenuOptions',
+ })
+ .catch((error: BusinessError) => {
+ hilog.error(DOMAIN, TAG, BUNDLE + `pushUrl failed, code is ${error.code}, message is ${error.message}`);
+ })
+ })
+
+ Button('scanQRCode')
+ .onClick(() => {
+ this.getUIContext().getRouter().pushUrl({
+ url: 'pages/WebScanQRCode',
+ })
+ .catch((error: BusinessError) => {
+ hilog.error(DOMAIN, TAG, BUNDLE + `pushUrl failed, code is ${error.code}, message is ${error.message}`);
+ })
+ })
+
+ Button('disableLongPress')
+ .onClick(() => {
+ this.getUIContext().getRouter().pushUrl({
+ url: 'pages/WebDisableLongPress',
+ })
+ .catch((error: BusinessError) => {
+ hilog.error(DOMAIN, TAG, BUNDLE + `pushUrl failed, code is ${error.code}, message is ${error.message}`);
+ })
+ })
+ }.height('100%')
+ .width('100%')
+ }
+}
\ No newline at end of file
diff --git a/ArkWebKit/ArkWebMenu/entry/src/main/ets/pages/WebBindSelectionMenu.ets b/ArkWebKit/ArkWebMenu/entry/src/main/ets/pages/WebBindSelectionMenu.ets
new file mode 100644
index 0000000000000000000000000000000000000000..82dfa701e2d096aefd60bed022530baadf3e4abb
--- /dev/null
+++ b/ArkWebKit/ArkWebMenu/entry/src/main/ets/pages/WebBindSelectionMenu.ets
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2025 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+// [Start web_BindSelectionMenu]
+import { webview } from '@kit.ArkWeb';
+
+//substring index
+const SUBSTRING_INDEX: number = 19;
+
+interface PreviewBuilderParam {
+ previewImage: Resource | string | undefined;
+ width: number;
+ height: number;
+}
+
+@Builder function previewBuilderGlobal($$: PreviewBuilderParam) {
+ Column() {
+ Image($$.previewImage)
+ .objectFit(ImageFit.Fill)
+ .autoResize(true)
+ }.width($$.width).height($$.height)
+}
+
+@Entry
+@Component
+struct WebComponent {
+ controller: webview.WebviewController = new webview.WebviewController();
+
+ private result: WebContextMenuResult | undefined = undefined;
+ @State previewImage: Resource | string | undefined = undefined;
+ @State previewWidth: number = 0;
+ @State previewHeight: number = 0;
+ uiContext: UIContext = this.getUIContext();
+
+ @Builder
+ MenuBuilder() {
+ Menu() {
+ MenuItem({ content: $r('app.string.copy'), })
+ .onClick(() => {
+ this.result?.copy();
+ this.result?.closeContextMenu();
+ })
+ MenuItem({ content: $r('app.string.all'), })
+ .onClick(() => {
+ this.result?.selectAll();
+ this.result?.closeContextMenu();
+ })
+ }
+ }
+ build() {
+ Column() {
+ Web({ src: $rawfile('index2.html'), controller: this.controller })
+ .bindSelectionMenu(WebElementType.IMAGE, this.MenuBuilder, WebResponseType.LONG_PRESS,
+ {
+ onAppear: () => {},
+ onDisappear: () => {
+ this.result?.closeContextMenu();
+ },
+ preview: previewBuilderGlobal({
+ previewImage: this.previewImage,
+ width: this.previewWidth,
+ height: this.previewHeight
+ }),
+ menuType: MenuType.PREVIEW_MENU
+ })
+ .onContextMenuShow((event) => {
+ if (event) {
+ this.result = event.result;
+ if (event.param.getLinkUrl()) {
+ return false;
+ }
+ this.previewWidth = this.uiContext!.px2vp(event.param.getPreviewWidth());
+ this.previewHeight = this.uiContext!.px2vp(event.param.getPreviewHeight());
+ if (event.param.getSourceUrl().indexOf('resource://rawfile/') == 0) {
+ this.previewImage = $rawfile(event.param.getSourceUrl().substr(SUBSTRING_INDEX));
+ } else {
+ this.previewImage = event.param.getSourceUrl();
+ }
+ return true;
+ }
+ return false;
+ })
+ }
+ }
+}
+// [End web_BindSelectionMenu]
\ No newline at end of file
diff --git a/ArkWebKit/ArkWebMenu/entry/src/main/ets/pages/WebContextMenu.ets b/ArkWebKit/ArkWebMenu/entry/src/main/ets/pages/WebContextMenu.ets
new file mode 100644
index 0000000000000000000000000000000000000000..374346d415c85a8554e33f675154941e6137fa58
--- /dev/null
+++ b/ArkWebKit/ArkWebMenu/entry/src/main/ets/pages/WebContextMenu.ets
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2025 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+// [Start web_ContextMenu]
+import { webview } from '@kit.ArkWeb';
+import { pasteboard } from '@kit.BasicServicesKit';
+import hilog from '@ohos.hilog';
+
+const TAG = '[Sample_ContextMenu]'
+const DOMAIN = 0xF811
+const BUNDLE = 'ContextMenu_'
+
+//MenuItem width
+const MENUITEM_WIDTH: number = 100;
+//MenuItem height
+const MENUITEM_HEIGHT: number = 50;
+//MenuBuilder width
+const MENUBUILDER_WIDTH: number = 150;
+//MenuBuilder height
+const MENUBUILDER_HEIGHT: number = 300;
+
+@Entry
+@Component
+struct WebComponent {
+ controller: webview.WebviewController = new webview.WebviewController();
+ private result: WebContextMenuResult | undefined = undefined;
+ @State linkUrl: string = '';
+ @State offsetX: number = 0;
+ @State offsetY: number = 0;
+ @State showMenu: boolean = false;
+ uiContext: UIContext = this.getUIContext();
+
+ @Builder
+ // 构建自定义菜单及触发功能接口
+ MenuBuilder() {
+ // 以垂直列表形式显示的菜单。
+ Menu() {
+ // 展示菜单Menu中具体的item菜单项。
+ MenuItem({
+ content: $r('app.string.copy_image'),
+ })
+ .width(MENUITEM_WIDTH)
+ .height(MENUITEM_HEIGHT)
+ .onClick(() => {
+ this.result?.copyImage();
+ this.showMenu = false;
+ })
+ MenuItem({
+ content: $r('app.string.cut'),
+ })
+ .width(MENUITEM_WIDTH)
+ .height(MENUITEM_HEIGHT)
+ .onClick(() => {
+ this.result?.cut();
+ this.showMenu = false;
+ })
+ MenuItem({
+ content: $r('app.string.copy'),
+ })
+ .width(MENUITEM_WIDTH)
+ .height(MENUITEM_HEIGHT)
+ .onClick(() => {
+ this.result?.copy();
+ this.showMenu = false;
+ })
+ MenuItem({
+ content: $r('app.string.paste'),
+ })
+ .width(MENUITEM_WIDTH)
+ .height(MENUITEM_HEIGHT)
+ .onClick(() => {
+ this.result?.paste();
+ this.showMenu = false;
+ })
+ MenuItem({
+ content: $r('app.string.copy_url'),
+ })
+ .width(MENUITEM_WIDTH)
+ .height(MENUITEM_HEIGHT)
+ .onClick(() => {
+ let pasteData = pasteboard.createData('text/plain', this.linkUrl);
+ pasteboard.getSystemPasteboard().setData(pasteData, (error) => {
+ if (error) {
+ return;
+ }
+ })
+ this.showMenu = false;
+ })
+ MenuItem({
+ content: $r('app.string.all'),
+ })
+ .width(MENUITEM_WIDTH)
+ .height(MENUITEM_HEIGHT)
+ .onClick(() => {
+ this.result?.selectAll();
+ this.showMenu = false;
+ })
+ }
+ .width(MENUBUILDER_WIDTH)
+ .height(MENUBUILDER_HEIGHT)
+ }
+
+ build() {
+ Column() {
+ Web({ src: $rawfile('index1.html'), controller: this.controller })
+ // 触发自定义弹窗
+ .onContextMenuShow((event) => {
+ if (event) {
+ this.result = event.result
+ hilog.info(DOMAIN, TAG, BUNDLE + 'x coord = ' + event.param.x());
+ hilog.info(DOMAIN, TAG, BUNDLE + 'link url = ' + event.param.getLinkUrl());
+ this.linkUrl = event.param.getLinkUrl();
+ }
+ hilog.info(DOMAIN, TAG, BUNDLE + `x: ${this.offsetX}, y: ${this.offsetY}`);
+ this.showMenu = true;
+ this.offsetX = 0;
+ this.offsetY = Math.max(this.uiContext!.px2vp(event?.param.y() ?? 0) - 0, 0);
+ return true;
+ })
+ .bindPopup(this.showMenu,
+ {
+ builder: this.MenuBuilder(),
+ enableArrow: false,
+ placement: Placement.LeftTop,
+ offset: { x: this.offsetX, y: this.offsetY },
+ mask: false,
+ onStateChange: (e) => {
+ if (!e.isVisible) {
+ this.showMenu = false;
+ this.result!.closeContextMenu();
+ }
+ }
+ })
+ }
+ }
+}
+// [End web_ContextMenu]
\ No newline at end of file
diff --git a/ArkWebKit/ArkWebMenu/entry/src/main/ets/pages/WebDisableLongPress.ets b/ArkWebKit/ArkWebMenu/entry/src/main/ets/pages/WebDisableLongPress.ets
new file mode 100644
index 0000000000000000000000000000000000000000..d6996667f03bab5a2eed0915b1c7e257bf4fe728
--- /dev/null
+++ b/ArkWebKit/ArkWebMenu/entry/src/main/ets/pages/WebDisableLongPress.ets
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2025 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+// [Start web_Disable_long_press]
+import { webview } from '@kit.ArkWeb';
+@Entry
+@Component
+struct WebComponent {
+ controller: webview.WebviewController = new webview.WebviewController();
+
+ onCreateMenu(menuItems: Array
选中文字鼠标右键弹出菜单
+ + \ No newline at end of file diff --git a/ArkWebKit/ArkWebMenu/entry/src/main/resources/rawfile/index2.html b/ArkWebKit/ArkWebMenu/entry/src/main/resources/rawfile/index2.html new file mode 100644 index 0000000000000000000000000000000000000000..9088b78dac25f4e36c882d54edff39bb229d52d6 --- /dev/null +++ b/ArkWebKit/ArkWebMenu/entry/src/main/resources/rawfile/index2.html @@ -0,0 +1,12 @@ + + + + +
+
+
\ No newline at end of file
diff --git a/ArkWebKit/ArkWebMenu/entry/src/main/resources/rawfile/index3.html b/ArkWebKit/ArkWebMenu/entry/src/main/resources/rawfile/index3.html
new file mode 100644
index 0000000000000000000000000000000000000000..d6ff0978094a73010c7136a628269e8a52571a3d
--- /dev/null
+++ b/ArkWebKit/ArkWebMenu/entry/src/main/resources/rawfile/index3.html
@@ -0,0 +1,19 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ArkWebKit/ArkWebMenu/entry/src/main/resources/rawfile/index7.html b/ArkWebKit/ArkWebMenu/entry/src/main/resources/rawfile/index7.html
new file mode 100644
index 0000000000000000000000000000000000000000..b97483aa41a95c609d25fa58cc77a3454af01e1d
--- /dev/null
+++ b/ArkWebKit/ArkWebMenu/entry/src/main/resources/rawfile/index7.html
@@ -0,0 +1,11 @@
+
+
+
+
+