@react-native-ohos/react-native-webview 13.16.1 → 13.16.2-beta.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/CHANGELOG.md +132 -0
  2. package/LICENSE +20 -20
  3. package/README.OpenSource +10 -10
  4. package/README.md +396 -13
  5. package/harmony/rn_webview/.gitignore +6 -0
  6. package/harmony/rn_webview/BuildProfile.ets +17 -0
  7. package/harmony/rn_webview/OAT.xml +44 -44
  8. package/harmony/rn_webview/build-profile.json5 +28 -28
  9. package/harmony/rn_webview/index.ets +12 -12
  10. package/harmony/rn_webview/oh-package-lock.json5 +28 -18
  11. package/harmony/rn_webview/oh-package.json5 +13 -13
  12. package/harmony/rn_webview/src/main/cpp/CMakeLists.txt +9 -9
  13. package/harmony/rn_webview/src/main/cpp/WebViewPackage.h +16 -16
  14. package/harmony/rn_webview/src/main/cpp/generated/RNOH/generated/BaseReactNativeWebviewPackage.h +96 -96
  15. package/harmony/rn_webview/src/main/cpp/generated/RNOH/generated/components/RNCWebViewJSIBinder.h +121 -120
  16. package/harmony/rn_webview/src/main/cpp/generated/RNOH/generated/turbo_modules/RNCWebView.cpp +18 -18
  17. package/harmony/rn_webview/src/main/cpp/generated/RNOH/generated/turbo_modules/RNCWebView.h +16 -16
  18. package/harmony/rn_webview/src/main/cpp/generated/RNOH/generated/turbo_modules/RNCWebViewModule.cpp +17 -17
  19. package/harmony/rn_webview/src/main/cpp/generated/RNOH/generated/turbo_modules/RNCWebViewModule.h +16 -16
  20. package/harmony/rn_webview/src/main/cpp/generated/react/renderer/components/react_native_webview/ComponentDescriptors.h +24 -24
  21. package/harmony/rn_webview/src/main/cpp/generated/react/renderer/components/react_native_webview/EventEmitters.cpp +258 -258
  22. package/harmony/rn_webview/src/main/cpp/generated/react/renderer/components/react_native_webview/EventEmitters.h +277 -277
  23. package/harmony/rn_webview/src/main/cpp/generated/react/renderer/components/react_native_webview/Props.cpp +104 -103
  24. package/harmony/rn_webview/src/main/cpp/generated/react/renderer/components/react_native_webview/Props.h +510 -509
  25. package/harmony/rn_webview/src/main/cpp/generated/react/renderer/components/react_native_webview/ShadowNodes.cpp +17 -17
  26. package/harmony/rn_webview/src/main/cpp/generated/react/renderer/components/react_native_webview/ShadowNodes.h +32 -32
  27. package/harmony/rn_webview/src/main/cpp/generated/react/renderer/components/react_native_webview/States.cpp +16 -16
  28. package/harmony/rn_webview/src/main/cpp/generated/react/renderer/components/react_native_webview/States.h +28 -28
  29. package/harmony/rn_webview/src/main/ets/CutomReference.ts +29 -29
  30. package/harmony/rn_webview/src/main/ets/Logger.ts +43 -43
  31. package/harmony/rn_webview/src/main/ets/Magic.ets +199 -184
  32. package/harmony/rn_webview/src/main/ets/RNCWebView.ets +824 -688
  33. package/harmony/rn_webview/src/main/ets/RNCWebViewPackage.ets +37 -37
  34. package/harmony/rn_webview/src/main/ets/ShouldRequestUrl.ts +47 -47
  35. package/harmony/rn_webview/src/main/ets/WebViewBaseOperate.ets +514 -501
  36. package/harmony/rn_webview/src/main/ets/WebViewTurboModule.ets +62 -62
  37. package/harmony/rn_webview/src/main/ets/generated/components/RNCWebView.ts +529 -525
  38. package/harmony/rn_webview/src/main/ets/generated/components/ts.ts +5 -5
  39. package/harmony/rn_webview/src/main/ets/generated/index.ets +5 -5
  40. package/harmony/rn_webview/src/main/ets/generated/ts.ts +6 -6
  41. package/harmony/rn_webview/src/main/ets/generated/turboModules/RNCWebView.ts +18 -18
  42. package/harmony/rn_webview/src/main/ets/generated/turboModules/RNCWebViewModule.ts +16 -16
  43. package/harmony/rn_webview/src/main/ets/generated/turboModules/ts.ts +6 -6
  44. package/harmony/rn_webview/src/main/module.json5 +10 -10
  45. package/harmony/rn_webview/src/main/resources/base/element/string.json +39 -39
  46. package/harmony/rn_webview/src/main/resources/en_US/element/string.json +39 -39
  47. package/harmony/rn_webview/src/main/resources/zh_CN/element/string.json +39 -39
  48. package/harmony/rn_webview/src/test/List.test.ets +4 -4
  49. package/harmony/rn_webview/src/test/LocalUnit.test.ets +32 -32
  50. package/harmony/rn_webview/ts.ets +8 -8
  51. package/harmony/rn_webview.har +0 -0
  52. package/lib/NativeRNCWebView.d.ts +10 -0
  53. package/lib/NativeRNCWebView.d.ts.map +1 -0
  54. package/lib/NativeRNCWebView.js +1 -0
  55. package/lib/NativeRNCWebViewModule.d.ts +9 -0
  56. package/lib/NativeRNCWebViewModule.d.ts.map +1 -0
  57. package/lib/NativeRNCWebViewModule.js +1 -0
  58. package/lib/RNCWebViewNativeComponent.d.ts +250 -0
  59. package/lib/RNCWebViewNativeComponent.d.ts.map +1 -0
  60. package/lib/RNCWebViewNativeComponent.js +1 -0
  61. package/lib/WebView.d.ts +4 -0
  62. package/lib/WebView.d.ts.map +1 -0
  63. package/lib/WebView.harmony.d.ts +16 -0
  64. package/lib/WebView.harmony.d.ts.map +1 -0
  65. package/lib/WebView.harmony.js +1 -0
  66. package/lib/WebView.js +1 -0
  67. package/lib/codegenUtils.d.ts +3 -0
  68. package/lib/codegenUtils.d.ts.map +1 -0
  69. package/lib/codegenUtils.js +0 -0
  70. package/lib/index.d.ts +4 -0
  71. package/lib/index.d.ts.map +1 -0
  72. package/lib/index.js +1 -0
  73. package/package.json +101 -99
  74. package/src/NativeRNCWebView.ts +21 -21
  75. package/src/NativeRNCWebViewModule.ts +19 -19
  76. package/src/RNCWebViewNativeComponent.ts +356 -355
  77. package/src/WebView.harmony.tsx +348 -346
  78. package/src/WebView.tsx +10 -10
  79. package/src/codegenUtils.ts +10 -10
  80. package/src/index.ts +10 -10
@@ -1,501 +1,514 @@
1
- // Copyright (c) 2025 Huawei Device Co., Ltd. All rights reserved
2
- // Use of this source code is governed by a Apache-2.0 license that can be
3
- // found in the LICENSE file.
4
-
5
- import { RNC } from './generated/ts'
6
- import { webview } from '@kit.ArkWeb'
7
- import { CACHE_MODE, COMMAND_NAME, ONE_HUNDRED, WebViewEventParams } from './Magic';
8
- import Logger from './Logger';
9
- import { common, ConfigurationConstant } from '@kit.AbilityKit';
10
-
11
- export const TAG = "WebView"
12
-
13
-
14
- interface ProgressInterface {
15
- progress: number;
16
- }
17
-
18
- interface CreateWebViewEventInterface {
19
- type: string;
20
- progress: number;
21
- }
22
-
23
- export class BaseOperate {
24
- private static LOCK_IDENTIFIER = 0
25
- private eventEmitter: RNC.RNCWebView.EventEmitter
26
- private controller: webview.WebviewController
27
- private lockIdentifier: number = 0
28
-
29
- constructor(eventEmitter: RNC.RNCWebView.EventEmitter, controller: webview.WebviewController) {
30
- this.eventEmitter = eventEmitter
31
- this.controller = controller
32
- this.lockIdentifier = BaseOperate.generateLockIdentifier()
33
- }
34
-
35
- static setThirdPartyCookiesEnabled(status: boolean) {
36
- try {
37
- webview.WebCookieManager.putAcceptThirdPartyCookieEnabled(status);
38
- } catch (error) {
39
- Logger.error(TAG, `[RNOH] setThirdPartyCookiesEnabled Errorcode: ${error.code}`);
40
- }
41
- }
42
-
43
- static getColorMode(context: common.UIAbilityContext, forceDarkOn: boolean): WebDarkMode {
44
- try {
45
- return ((context.config.colorMode === ConfigurationConstant.ColorMode.COLOR_MODE_DARK) && forceDarkOn) ?
46
- WebDarkMode.On : WebDarkMode.Off
47
- } catch (error) {
48
- Logger.error(TAG, `[RNOH] getColorMode Errorcode: ${error.code}`);
49
- return WebDarkMode.Off
50
- }
51
- }
52
-
53
- static generateLockIdentifier(): number {
54
- BaseOperate.LOCK_IDENTIFIER = BaseOperate.LOCK_IDENTIFIER + 1
55
- return BaseOperate.LOCK_IDENTIFIER
56
- }
57
-
58
- getLockIdentifier():number {
59
- return this.lockIdentifier
60
- }
61
-
62
- setLockIdentifier(lockIdentifier: number) {
63
- this.lockIdentifier = lockIdentifier
64
- }
65
-
66
- emitProgressChange(params: ProgressInterface) {
67
- try {
68
- this.eventEmitter!.emit('loadingProgress', {
69
- url: this.controller.getUrl(),
70
- loading: params.progress != ONE_HUNDRED,
71
- title: this.controller.getTitle(),
72
- canGoBack: this.controller.accessBackward(),
73
- canGoForward: this.controller.accessForward(),
74
- lockIdentifier: this.lockIdentifier,
75
- progress: params.progress / ONE_HUNDRED
76
- })
77
- } catch (error) {
78
- Logger.error(TAG, `[RNOH] emitProgressChange Errorcode: ${error.code}`);
79
- }
80
- }
81
-
82
- emitLoadingStart(params: ProgressInterface) {
83
- try {
84
- this.eventEmitter!.emit('loadingStart', {
85
- url: this.controller.getUrl(),
86
- loading: params.progress != ONE_HUNDRED,
87
- title: this.controller.getTitle(),
88
- canGoBack: this.controller.accessBackward(),
89
- canGoForward: this.controller.accessForward(),
90
- lockIdentifier: this.lockIdentifier,
91
- navigationType: "other",
92
- mainDocumentURL: ""
93
- })
94
- } catch (error) {
95
- Logger.error(TAG, `[RNOH] emitLoadingStart Errorcode: ${error.code}`);
96
- }
97
- }
98
-
99
- emitLoadingFinish(params: ProgressInterface) {
100
- try {
101
- this.eventEmitter!.emit('loadingFinish', {
102
- url: this.controller.getUrl(),
103
- loading: params.progress != ONE_HUNDRED,
104
- title: this.controller.getTitle(),
105
- canGoBack: this.controller.accessBackward(),
106
- canGoForward: this.controller.accessForward(),
107
- lockIdentifier: this.lockIdentifier,
108
- navigationType: "other",
109
- mainDocumentURL: ""
110
- })
111
- } catch (error) {
112
- Logger.error(TAG, `[RNOH] emitLoadingFinish Errorcode: ${error.code}`);
113
- }
114
- }
115
-
116
- emitLoadingError(event: OnErrorReceiveEvent) {
117
- try {
118
- if (!event.request.isMainFrame()) {
119
- Logger.debug(TAG, "[RNOH] Not Main Frame Error");
120
- return;
121
- }
122
- this.eventEmitter!.emit('loadingError', {
123
- url: this.controller.getUrl(),
124
- loading: false,
125
- title: this.controller.getTitle(),
126
- canGoBack: this.controller.accessBackward(),
127
- canGoForward: this.controller.accessForward(),
128
- lockIdentifier: this.lockIdentifier,
129
- domain: "",
130
- code: event.error.getErrorCode(),
131
- description: event.error.getErrorInfo()
132
- })
133
- } catch (error) {
134
- Logger.error(TAG, `[RNOH] emitLoadingError Errorcode: ${error.code}`);
135
- }
136
- }
137
-
138
- emitOnSslErrorEventCallback(event: SslErrorEvent) {
139
- try {
140
- const referrerUrl = event.referrer;
141
- const url = event.url;
142
- event.handler.handleCancel(true);
143
- if (referrerUrl.toLowerCase() != url.toLowerCase()) {
144
- Logger.debug(TAG, "[RNOH] Resource blocked from loading due to SSL error. Blocked URL: " + url);
145
- let description = "";
146
- const descriptionPrefix = "SSL error: ";
147
- switch (event.error) {
148
- case SslError.DateInvalid:
149
- description = "The date of the certificate is invalid";
150
- break;
151
- case SslError.HostMismatch:
152
- description = "Hostname mismatch";
153
- break;
154
- case SslError.Invalid:
155
- description = "A generic error occurred";
156
- break;
157
- case SslError.Untrusted:
158
- description = "The certificate authority is not trusted";
159
- break;
160
- default:
161
- description = "Unknown SSL Error";
162
- break;
163
- }
164
- description = descriptionPrefix + description;
165
- this.eventEmitter!.emit('loadingSubResourceError', {
166
- url: event.url,
167
- loading: false,
168
- title: this.controller.getTitle(),
169
- canGoBack: this.controller.accessBackward(),
170
- canGoForward: this.controller.accessForward(),
171
- lockIdentifier: this.lockIdentifier,
172
- domain: "",
173
- code: event.error,
174
- description: description
175
- })
176
- }
177
- } catch (error) {
178
- Logger.error(TAG, `[RNOH] emitLoadingError Errorcode: ${error.code}`);
179
- }
180
- }
181
-
182
- emitHttpError(event: OnHttpErrorReceiveEvent) {
183
- try {
184
- this.eventEmitter!.emit('httpError', {
185
- url: this.controller.getUrl(),
186
- loading: false,
187
- title: this.controller.getTitle(),
188
- canGoBack: this.controller.accessBackward(),
189
- canGoForward: this.controller.accessForward(),
190
- lockIdentifier: this.lockIdentifier,
191
- description: event.response.getResponseData(),
192
- statusCode: event.response.getResponseCode()
193
- })
194
- } catch (error) {
195
- Logger.error(TAG, `[RNOH] emitHttpError Errorcode: ${error.code}`);
196
- }
197
- }
198
-
199
- emitScroll(event: OnScrollEvent) {
200
- try {
201
- this.eventEmitter!.emit('scroll', {
202
- contentInset: {
203
- bottom: 0,
204
- left: 0,
205
- right: 0,
206
- top: 0
207
- },
208
- contentOffset: { y: event.yOffset, x: event.xOffset },
209
- contentSize: { height: 0, width: 0 },
210
- layoutMeasurement: { height: 0, width: 0 }
211
- })
212
- } catch (error) {
213
- Logger.error(TAG, `[RNOH] emitScroll Errorcode: ${error.code}`);
214
- }
215
- }
216
-
217
- verifyURLFormat(url: string, html: string | undefined, baseUrl: string | undefined) {
218
- const dataUrlPattern = /^data:text\/html;/;
219
- if (dataUrlPattern.test(url)){
220
- if (html != undefined && html != "") {
221
- if (baseUrl != undefined && baseUrl != "") {
222
- url = baseUrl.toLowerCase();
223
- } else {
224
- url = 'about:blank';
225
- }
226
- }
227
- }
228
- return url;
229
- }
230
-
231
- emitShouldStartLoadWithRequest(event: OnLoadInterceptEvent, html: string | undefined, baseUrl: string | undefined) {
232
- try {
233
- this.eventEmitter!.emit('shouldStartLoadWithRequest', {
234
- url: this.verifyURLFormat(event.data.getRequestUrl(), html, baseUrl),
235
- loading: false,
236
- title: this.controller.getTitle(),
237
- canGoBack: this.controller.accessBackward(),
238
- canGoForward: this.controller.accessForward(),
239
- lockIdentifier: this.lockIdentifier,
240
- navigationType: "other",
241
- mainDocumentURL: "",
242
- isTopFrame: false
243
- })
244
- } catch (error) {
245
- Logger.error(TAG, `[RNOH] emitShouldStartLoadWithRequest Errorcode: ${error.code}`);
246
- }
247
- }
248
-
249
- emitShouldStartLoadWithRequestOverrideUrlLoading(event: WebResourceRequest) {
250
- try {
251
- this.eventEmitter!.emit('shouldStartLoadWithRequest', {
252
- url: event.getRequestUrl(),
253
- loading: false,
254
- title: this.controller.getTitle(),
255
- canGoBack: this.controller.accessBackward(),
256
- canGoForward: this.controller.accessForward(),
257
- lockIdentifier: this.lockIdentifier,
258
- navigationType: "other",
259
- mainDocumentURL: "",
260
- isTopFrame: false
261
- })
262
- } catch (error) {
263
- Logger.error(TAG, `[RNOH] emitShouldStartLoadWithRequest Errorcode: ${error.code}`);
264
- }
265
- }
266
-
267
- transCacheMode(cacheMode: CACHE_MODE): CacheMode {
268
- let mode = CacheMode.Default
269
- switch (cacheMode) {
270
- case CACHE_MODE.LOAD_DEFAULT:
271
- mode = CacheMode.Default
272
- break;
273
- case CACHE_MODE.LOAD_CACHE_ELSE_NETWORK:
274
- mode = CacheMode.None
275
- break;
276
- case CACHE_MODE.LOAD_NO_CACHE:
277
- mode = CacheMode.Online
278
- break;
279
- case CACHE_MODE.LOAD_CACHE_ONLY:
280
- mode = CacheMode.Only
281
- break;
282
- default:
283
- break;
284
- }
285
- return mode
286
- }
287
-
288
- createWebViewEvent(param: CreateWebViewEventInterface): WebViewEventParams {
289
- let result: WebViewEventParams = new WebViewEventParams(param.type);
290
- result.loading = param.progress != ONE_HUNDRED
291
- try {
292
- result.url = this.controller.getUrl();
293
- result.title = this.controller.getTitle();
294
- result.canGoBack = this.controller.accessBackward();
295
- result.canGoForward = this.controller.accessForward();
296
- } catch (error) {
297
- result.url = "";
298
- result.title = "";
299
- result.canGoBack = false;
300
- result.canGoForward = false;
301
- }
302
- return result;
303
- }
304
-
305
- // 与OS web同事 对齐 默认false 是取消静音
306
- ignoreSilentHardwareSwitchMethods(ignoreSilentHardwareSwitch: boolean) {
307
- this.controller.setAudioMuted(!ignoreSilentHardwareSwitch)
308
- }
309
-
310
- setCustomUserAgent(customUserAgent?: string, applicationNameForUserAgent?: string): void {
311
- try {
312
- if (customUserAgent) {
313
- let userAgent: string = customUserAgent;
314
- this.controller.setCustomUserAgent(userAgent);
315
- }
316
- if (applicationNameForUserAgent) {
317
- this.controller.setCustomUserAgent(`${this.controller.getUserAgent()}${applicationNameForUserAgent}`);
318
- }
319
- } catch (error) {
320
- Logger.debug(TAG,
321
- `[RNOH] setCustomUserAgent ErrorCode: ${error.code}, userAgent: ${customUserAgent}`);
322
- }
323
- }
324
-
325
- injectJavaScript(args: string[]) {
326
- try {
327
- this.controller.runJavaScript(args[0])
328
- } catch (error) {
329
- Logger.error(TAG, `[RNOH] injectJavaScript Errorcode: ${error.code}`);
330
- }
331
- }
332
-
333
- postMessage(args: string[]) {
334
- let data = JSON.stringify({ data: args[0] })
335
- let result: string = "(function () {" +
336
- "var event;" +
337
- "var data = " + data.toString() + ";" +
338
- "try {" +
339
- "event = new MessageEvent('message', data);" +
340
- "} catch (e) {" +
341
- "event = document.createEvent('MessageEvent');" +
342
- "event.initMessageEvent('message', true, true, data.data, data.origin, data.lastEventId, data.source);" +
343
- "}" +
344
- "document.dispatchEvent(event);" +
345
- "})();"
346
- try {
347
- this.controller.runJavaScript(result)
348
- } catch (error) {
349
- Logger.error(TAG, `[RNOH] postMessage Errorcode: ${error.code}`);
350
- }
351
- }
352
-
353
- reload() {
354
- try {
355
- this.controller.refresh();
356
- } catch (error) {
357
- Logger.error(TAG, `[RNOH] reload Errorcode: ${error.code}`);
358
- }
359
- }
360
-
361
- goBack() {
362
- try {
363
- this.controller.backward();
364
- } catch (error) {
365
- Logger.error(TAG, `[RNOH] goBack Errorcode: ${error.code}`);
366
- }
367
- }
368
-
369
- goForward() {
370
- try {
371
- this.controller.forward();
372
- } catch (error) {
373
- Logger.error(TAG, `[RNOH] goForward Errorcode: ${error.code}`);
374
- }
375
- }
376
-
377
- requestFocus() {
378
- try {
379
- this.controller.requestFocus();
380
- } catch (error) {
381
- Logger.error(TAG, `[RNOH] requestFocus Errorcode: ${error.code}`);
382
- }
383
- }
384
-
385
- clearCache(args: string[]) {
386
- try {
387
- const removeFlag = !!args[0] === true;
388
- this.controller.removeCache(removeFlag);
389
- } catch (error) {
390
- Logger.error(TAG, `[RNOH] clearCache Errorcode: ${error.code}`);
391
- }
392
- }
393
-
394
- clearHistory() {
395
- try {
396
- this.controller.clearHistory();
397
- } catch (error) {
398
- Logger.error(TAG, `[RNOH] clearHistory Errorcode: ${error.code}`);
399
- }
400
- }
401
-
402
- stopLoading() {
403
- try {
404
- this.controller.stop();
405
- } catch (error) {
406
- Logger.error(TAG, `[RNOH] stopLoading Errorcode: ${error.code}`);
407
- }
408
- }
409
-
410
- loadUrl(args: string[]) {
411
- try {
412
- this.controller.loadUrl(args[0]);
413
- } catch (error) {
414
- Logger.error(TAG, `[RNOH] loadUrl Errorcode: ${error.code}`);
415
- }
416
- }
417
-
418
- registerCommandCallback(commandName: COMMAND_NAME, args: string[]) {
419
- switch (commandName) {
420
- case COMMAND_NAME.INJECTJAVASCRIPT:
421
- this.injectJavaScript(args)
422
- break
423
- case COMMAND_NAME.POSTMESSAGE:
424
- this.postMessage(args)
425
- break
426
- case COMMAND_NAME.RELOAD:
427
- this.reload()
428
- break
429
- case COMMAND_NAME.GOBACK:
430
- this.goBack()
431
- break
432
- case COMMAND_NAME.GOFORWARD:
433
- this.goForward()
434
- break
435
- case COMMAND_NAME.REQUESTFOCUS:
436
- this.requestFocus()
437
- case COMMAND_NAME.CLEARCACHE:
438
- this.clearCache(args)
439
- case COMMAND_NAME.CLEARHISTORY:
440
- this.clearHistory()
441
- break
442
- case COMMAND_NAME.STOPLOADING:
443
- this.stopLoading()
444
- break
445
- case COMMAND_NAME.LOADURL:
446
- this.loadUrl(args)
447
- break
448
- default:
449
- break
450
- }
451
- }
452
-
453
- setOriginWhitelist(uris: string) {
454
- try {
455
- this.controller.setUrlTrustList(uris);
456
- } catch (error) {
457
- Logger.error(TAG, `[RNOH] setOriginWhitelist Errorcode: ${error.code}`);
458
- }
459
- }
460
-
461
- setIncognito() {
462
- this.controller.clearHistory()
463
- webview.WebCookieManager.clearAllCookiesSync(true);
464
- webview.WebCookieManager.clearSessionCookieSync()
465
- webview.WebStorage.deleteAllData();
466
- }
467
-
468
- setFraudulentWebsiteWarningEnabled(status: boolean) {
469
- try {
470
- this.controller.enableSafeBrowsing(status);
471
- } catch (error) {
472
- Logger.error(TAG, `[RNOH] setFraudulentWebsiteWarningEnabled Errorcode: ${error.code}`);
473
- }
474
- }
475
-
476
- onDownloadStart(event: OnDownloadStartEvent) {
477
- try {
478
- this.eventEmitter!.emit('fileDownload', {
479
- downloadUrl: event.url
480
- })
481
- } catch (error) {
482
- Logger.error(TAG, `[RNOH] onDownloadStart Errorcode: ${error.code}`);
483
- }
484
- }
485
-
486
- onRenderExited(event: OnRenderExitedEvent) {
487
- try {
488
-
489
- } catch (error) {
490
- Logger.error(TAG, `[RNOH] onRenderExited Errorcode: ${error.code}`);
491
- }
492
- }
493
-
494
- onTitleReceive(event: OnTitleReceiveEvent) {
495
- try {
496
-
497
- } catch (error) {
498
- Logger.error(TAG, `[RNOH] onTitleReceive Errorcode: ${error.code}`);
499
- }
500
- }
501
- }
1
+ // Copyright (c) 2025 Huawei Device Co., Ltd. All rights reserved
2
+ // Use of this source code is governed by a Apache-2.0 license that can be
3
+ // found in the LICENSE file.
4
+
5
+ import { RNC } from './generated/ts'
6
+ import { webview } from '@kit.ArkWeb'
7
+ import { CACHE_MODE, COMMAND_NAME, ONE_HUNDRED, WebViewEventParams } from './Magic';
8
+ import Logger from './Logger';
9
+ import { common, ConfigurationConstant } from '@kit.AbilityKit';
10
+
11
+ export const TAG = "WebView"
12
+
13
+
14
+ interface ProgressInterface {
15
+ progress: number;
16
+ }
17
+
18
+ interface CreateWebViewEventInterface {
19
+ type: string;
20
+ progress: number;
21
+ }
22
+
23
+ export class BaseOperate {
24
+ private static LOCK_IDENTIFIER = 0
25
+ private eventEmitter: RNC.RNCWebView.EventEmitter
26
+ private controller: webview.WebviewController
27
+ private lockIdentifier: number = 0
28
+
29
+ constructor(eventEmitter: RNC.RNCWebView.EventEmitter, controller: webview.WebviewController) {
30
+ this.eventEmitter = eventEmitter
31
+ this.controller = controller
32
+ this.lockIdentifier = BaseOperate.generateLockIdentifier()
33
+ }
34
+
35
+ static setThirdPartyCookiesEnabled(status: boolean) {
36
+ try {
37
+ webview.WebCookieManager.putAcceptThirdPartyCookieEnabled(status);
38
+ } catch (error) {
39
+ Logger.error(TAG, `[RNOH] setThirdPartyCookiesEnabled Errorcode: ${error.code}`);
40
+ }
41
+ }
42
+
43
+ static getColorMode(context: common.UIAbilityContext, forceDarkOn: boolean): WebDarkMode {
44
+ try {
45
+ return ((context.config.colorMode === ConfigurationConstant.ColorMode.COLOR_MODE_DARK) && forceDarkOn) ?
46
+ WebDarkMode.On : WebDarkMode.Off
47
+ } catch (error) {
48
+ Logger.error(TAG, `[RNOH] getColorMode Errorcode: ${error.code}`);
49
+ return WebDarkMode.Off
50
+ }
51
+ }
52
+
53
+ static generateLockIdentifier(): number {
54
+ BaseOperate.LOCK_IDENTIFIER = BaseOperate.LOCK_IDENTIFIER + 1
55
+ return BaseOperate.LOCK_IDENTIFIER
56
+ }
57
+
58
+ getLockIdentifier():number {
59
+ return this.lockIdentifier
60
+ }
61
+
62
+ setLockIdentifier(lockIdentifier: number) {
63
+ this.lockIdentifier = lockIdentifier
64
+ }
65
+
66
+ emitProgressChange(params: ProgressInterface) {
67
+ try {
68
+ this.eventEmitter!.emit('loadingProgress', {
69
+ url: this.controller.getUrl(),
70
+ loading: params.progress != ONE_HUNDRED,
71
+ title: this.controller.getTitle(),
72
+ canGoBack: this.controller.accessBackward(),
73
+ canGoForward: this.controller.accessForward(),
74
+ lockIdentifier: this.lockIdentifier,
75
+ progress: params.progress / ONE_HUNDRED
76
+ })
77
+ } catch (error) {
78
+ Logger.error(TAG, `[RNOH] emitProgressChange Errorcode: ${error.code}`);
79
+ }
80
+ }
81
+
82
+ emitLoadingStart(params: ProgressInterface) {
83
+ try {
84
+ this.eventEmitter!.emit('loadingStart', {
85
+ url: this.controller.getUrl(),
86
+ loading: params.progress != ONE_HUNDRED,
87
+ title: this.controller.getTitle(),
88
+ canGoBack: this.controller.accessBackward(),
89
+ canGoForward: this.controller.accessForward(),
90
+ lockIdentifier: this.lockIdentifier,
91
+ navigationType: "other",
92
+ mainDocumentURL: ""
93
+ })
94
+ } catch (error) {
95
+ Logger.error(TAG, `[RNOH] emitLoadingStart Errorcode: ${error.code}`);
96
+ }
97
+ }
98
+
99
+ emitLoadingFinish(params: ProgressInterface) {
100
+ try {
101
+ this.eventEmitter!.emit('loadingFinish', {
102
+ url: this.controller.getUrl(),
103
+ loading: params.progress != ONE_HUNDRED,
104
+ title: this.controller.getTitle(),
105
+ canGoBack: this.controller.accessBackward(),
106
+ canGoForward: this.controller.accessForward(),
107
+ lockIdentifier: this.lockIdentifier,
108
+ navigationType: "other",
109
+ mainDocumentURL: ""
110
+ })
111
+ } catch (error) {
112
+ Logger.error(TAG, `[RNOH] emitLoadingFinish Errorcode: ${error.code}`);
113
+ }
114
+ }
115
+
116
+ emitLoadingError(event: OnErrorReceiveEvent) {
117
+ try {
118
+ if (!event.request.isMainFrame()) {
119
+ Logger.debug(TAG, "[RNOH] Not Main Frame Error");
120
+ return;
121
+ }
122
+ this.eventEmitter!.emit('loadingError', {
123
+ url: this.controller.getUrl(),
124
+ loading: false,
125
+ title: this.controller.getTitle(),
126
+ canGoBack: this.controller.accessBackward(),
127
+ canGoForward: this.controller.accessForward(),
128
+ lockIdentifier: this.lockIdentifier,
129
+ domain: "",
130
+ code: event.error.getErrorCode(),
131
+ description: event.error.getErrorInfo()
132
+ })
133
+ } catch (error) {
134
+ Logger.error(TAG, `[RNOH] emitLoadingError Errorcode: ${error.code}`);
135
+ }
136
+ }
137
+
138
+ emitOnSslErrorEventCallback(event: SslErrorEvent) {
139
+ try {
140
+ const referrerUrl = event.referrer;
141
+ const url = event.url;
142
+ event.handler.handleCancel(true);
143
+ if (referrerUrl.toLowerCase() != url.toLowerCase()) {
144
+ Logger.debug(TAG, "[RNOH] Resource blocked from loading due to SSL error. Blocked URL: " + url);
145
+ let description = "";
146
+ const descriptionPrefix = "SSL error: ";
147
+ switch (event.error) {
148
+ case SslError.DateInvalid:
149
+ description = "The date of the certificate is invalid";
150
+ break;
151
+ case SslError.HostMismatch:
152
+ description = "Hostname mismatch";
153
+ break;
154
+ case SslError.Invalid:
155
+ description = "A generic error occurred";
156
+ break;
157
+ case SslError.Untrusted:
158
+ description = "The certificate authority is not trusted";
159
+ break;
160
+ default:
161
+ description = "Unknown SSL Error";
162
+ break;
163
+ }
164
+ description = descriptionPrefix + description;
165
+ this.eventEmitter!.emit('loadingSubResourceError', {
166
+ url: event.url,
167
+ loading: false,
168
+ title: this.controller.getTitle(),
169
+ canGoBack: this.controller.accessBackward(),
170
+ canGoForward: this.controller.accessForward(),
171
+ lockIdentifier: this.lockIdentifier,
172
+ domain: "",
173
+ code: event.error,
174
+ description: description
175
+ })
176
+ }
177
+ } catch (error) {
178
+ Logger.error(TAG, `[RNOH] emitLoadingError Errorcode: ${error.code}`);
179
+ }
180
+ }
181
+
182
+ emitHttpError(event: OnHttpErrorReceiveEvent) {
183
+ try {
184
+ this.eventEmitter!.emit('httpError', {
185
+ url: this.controller.getUrl(),
186
+ loading: false,
187
+ title: this.controller.getTitle(),
188
+ canGoBack: this.controller.accessBackward(),
189
+ canGoForward: this.controller.accessForward(),
190
+ lockIdentifier: this.lockIdentifier,
191
+ description: event.response.getResponseData(),
192
+ statusCode: event.response.getResponseCode()
193
+ })
194
+ } catch (error) {
195
+ Logger.error(TAG, `[RNOH] emitHttpError Errorcode: ${error.code}`);
196
+ }
197
+ }
198
+
199
+ emitScroll(event: OnScrollEvent) {
200
+ try {
201
+ this.eventEmitter!.emit('scroll', {
202
+ contentInset: {
203
+ bottom: 0,
204
+ left: 0,
205
+ right: 0,
206
+ top: 0
207
+ },
208
+ contentOffset: { y: event.yOffset, x: event.xOffset },
209
+ contentSize: { height: 0, width: 0 },
210
+ layoutMeasurement: { height: 0, width: 0 }
211
+ })
212
+ } catch (error) {
213
+ Logger.error(TAG, `[RNOH] emitScroll Errorcode: ${error.code}`);
214
+ }
215
+ }
216
+
217
+ verifyURLFormat(url: string, html: string | undefined, baseUrl: string | undefined) {
218
+ const dataUrlPattern = /^data:text\/html;/;
219
+ if (dataUrlPattern.test(url)){
220
+ if (html != undefined && html != "") {
221
+ if (baseUrl != undefined && baseUrl != "") {
222
+ url = baseUrl.toLowerCase();
223
+ } else {
224
+ url = 'about:blank';
225
+ }
226
+ }
227
+ }
228
+ return url;
229
+ }
230
+
231
+ emitShouldStartLoadWithRequest(event: OnLoadInterceptEvent, html: string | undefined, baseUrl: string | undefined) {
232
+ try {
233
+ this.eventEmitter!.emit('shouldStartLoadWithRequest', {
234
+ url: this.verifyURLFormat(event.data.getRequestUrl(), html, baseUrl),
235
+ loading: false,
236
+ title: this.controller.getTitle(),
237
+ canGoBack: this.controller.accessBackward(),
238
+ canGoForward: this.controller.accessForward(),
239
+ lockIdentifier: this.lockIdentifier,
240
+ navigationType: "other",
241
+ mainDocumentURL: "",
242
+ isTopFrame: false
243
+ })
244
+ } catch (error) {
245
+ Logger.error(TAG, `[RNOH] emitShouldStartLoadWithRequest Errorcode: ${error.code}`);
246
+ }
247
+ }
248
+
249
+ emitShouldStartLoadWithRequestOverrideUrlLoading(event: WebResourceRequest) {
250
+ try {
251
+ this.eventEmitter!.emit('shouldStartLoadWithRequest', {
252
+ url: event.getRequestUrl(),
253
+ loading: false,
254
+ title: this.controller.getTitle(),
255
+ canGoBack: this.controller.accessBackward(),
256
+ canGoForward: this.controller.accessForward(),
257
+ lockIdentifier: this.lockIdentifier,
258
+ navigationType: "other",
259
+ mainDocumentURL: "",
260
+ isTopFrame: false
261
+ })
262
+ } catch (error) {
263
+ Logger.error(TAG, `[RNOH] emitShouldStartLoadWithRequest Errorcode: ${error.code}`);
264
+ }
265
+ }
266
+
267
+ transCacheMode(cacheMode: CACHE_MODE): CacheMode {
268
+ let mode = CacheMode.Default
269
+ switch (cacheMode) {
270
+ case CACHE_MODE.LOAD_DEFAULT:
271
+ mode = CacheMode.Default
272
+ break;
273
+ case CACHE_MODE.LOAD_CACHE_ELSE_NETWORK:
274
+ mode = CacheMode.None
275
+ break;
276
+ case CACHE_MODE.LOAD_NO_CACHE:
277
+ mode = CacheMode.Online
278
+ break;
279
+ case CACHE_MODE.LOAD_CACHE_ONLY:
280
+ mode = CacheMode.Only
281
+ break;
282
+ default:
283
+ break;
284
+ }
285
+ return mode
286
+ }
287
+
288
+ createWebViewEvent(param: CreateWebViewEventInterface): WebViewEventParams {
289
+ let result: WebViewEventParams = new WebViewEventParams(param.type);
290
+ result.loading = param.progress != ONE_HUNDRED
291
+ try {
292
+ result.url = this.controller.getUrl();
293
+ result.title = this.controller.getTitle();
294
+ result.canGoBack = this.controller.accessBackward();
295
+ result.canGoForward = this.controller.accessForward();
296
+ } catch (error) {
297
+ result.url = "";
298
+ result.title = "";
299
+ result.canGoBack = false;
300
+ result.canGoForward = false;
301
+ }
302
+ return result;
303
+ }
304
+
305
+ // 与OS web同事 对齐 默认false 是取消静音
306
+ ignoreSilentHardwareSwitchMethods(ignoreSilentHardwareSwitch: boolean) {
307
+ this.controller.setAudioMuted(!ignoreSilentHardwareSwitch)
308
+ }
309
+
310
+ setCustomUserAgent(customUserAgent?: string, applicationNameForUserAgent?: string): void {
311
+ try {
312
+ if (customUserAgent) {
313
+ let userAgent: string = customUserAgent;
314
+ this.controller.setCustomUserAgent(userAgent);
315
+ }
316
+ if (applicationNameForUserAgent) {
317
+ this.controller.setCustomUserAgent(`${this.controller.getUserAgent()}${applicationNameForUserAgent}`);
318
+ }
319
+ } catch (error) {
320
+ Logger.debug(TAG,
321
+ `[RNOH] setCustomUserAgent ErrorCode: ${error.code}, userAgent: ${customUserAgent}`);
322
+ }
323
+ }
324
+
325
+ injectJavaScript(args: string[]) {
326
+ try {
327
+ this.controller.runJavaScript(args[0])
328
+ } catch (error) {
329
+ Logger.error(TAG, `[RNOH] injectJavaScript Errorcode: ${error.code}`);
330
+ }
331
+ }
332
+
333
+ postMessage(args: string[]) {
334
+ let data = JSON.stringify({ data: args[0] })
335
+ let result: string = "(function () {" +
336
+ "var event;" +
337
+ "var data = " + data.toString() + ";" +
338
+ "try {" +
339
+ "event = new MessageEvent('message', data);" +
340
+ "} catch (e) {" +
341
+ "event = document.createEvent('MessageEvent');" +
342
+ "event.initMessageEvent('message', true, true, data.data, data.origin, data.lastEventId, data.source);" +
343
+ "}" +
344
+ "document.dispatchEvent(event);" +
345
+ "})();"
346
+ try {
347
+ this.controller.runJavaScript(result)
348
+ } catch (error) {
349
+ Logger.error(TAG, `[RNOH] postMessage Errorcode: ${error.code}`);
350
+ }
351
+ }
352
+
353
+ reload() {
354
+ try {
355
+ this.controller.refresh();
356
+ } catch (error) {
357
+ Logger.error(TAG, `[RNOH] reload Errorcode: ${error.code}`);
358
+ }
359
+ }
360
+
361
+ goBack() {
362
+ try {
363
+ this.controller.backward();
364
+ } catch (error) {
365
+ Logger.error(TAG, `[RNOH] goBack Errorcode: ${error.code}`);
366
+ }
367
+ }
368
+
369
+ goForward() {
370
+ try {
371
+ this.controller.forward();
372
+ } catch (error) {
373
+ Logger.error(TAG, `[RNOH] goForward Errorcode: ${error.code}`);
374
+ }
375
+ }
376
+
377
+ requestFocus() {
378
+ try {
379
+ this.controller.requestFocus();
380
+ } catch (error) {
381
+ Logger.error(TAG, `[RNOH] requestFocus Errorcode: ${error.code}`);
382
+ }
383
+ }
384
+
385
+ clearCache(args: string[]) {
386
+ try {
387
+ const removeFlag = !!args[0] === true;
388
+ this.controller.removeCache(removeFlag);
389
+ } catch (error) {
390
+ Logger.error(TAG, `[RNOH] clearCache Errorcode: ${error.code}`);
391
+ }
392
+ }
393
+
394
+ clearHistory() {
395
+ try {
396
+ this.controller.clearHistory();
397
+ } catch (error) {
398
+ Logger.error(TAG, `[RNOH] clearHistory Errorcode: ${error.code}`);
399
+ }
400
+ }
401
+
402
+ stopLoading() {
403
+ try {
404
+ this.controller.stop();
405
+ } catch (error) {
406
+ Logger.error(TAG, `[RNOH] stopLoading Errorcode: ${error.code}`);
407
+ }
408
+ }
409
+
410
+ loadUrl(args: string[]) {
411
+ try {
412
+ this.controller.loadUrl(args[0]);
413
+ } catch (error) {
414
+ Logger.error(TAG, `[RNOH] loadUrl Errorcode: ${error.code}`);
415
+ }
416
+ }
417
+
418
+ registerCommandCallback(commandName: COMMAND_NAME, args: string[]) {
419
+ switch (commandName) {
420
+ case COMMAND_NAME.INJECTJAVASCRIPT:
421
+ this.injectJavaScript(args)
422
+ break
423
+ case COMMAND_NAME.POSTMESSAGE:
424
+ this.postMessage(args)
425
+ break
426
+ case COMMAND_NAME.RELOAD:
427
+ this.reload()
428
+ break
429
+ case COMMAND_NAME.GOBACK:
430
+ this.goBack()
431
+ break
432
+ case COMMAND_NAME.GOFORWARD:
433
+ this.goForward()
434
+ break
435
+ case COMMAND_NAME.REQUESTFOCUS:
436
+ this.requestFocus()
437
+ case COMMAND_NAME.CLEARCACHE:
438
+ this.clearCache(args)
439
+ case COMMAND_NAME.CLEARHISTORY:
440
+ this.clearHistory()
441
+ break
442
+ case COMMAND_NAME.STOPLOADING:
443
+ this.stopLoading()
444
+ break
445
+ case COMMAND_NAME.LOADURL:
446
+ this.loadUrl(args)
447
+ break
448
+ default:
449
+ break
450
+ }
451
+ }
452
+
453
+ setOriginWhitelist(uris: string) {
454
+ try {
455
+ this.controller.setUrlTrustList(uris);
456
+ } catch (error) {
457
+ Logger.error(TAG, `[RNOH] setOriginWhitelist Errorcode: ${error.code}`);
458
+ }
459
+ }
460
+
461
+ setIncognito() {
462
+ this.controller.clearHistory()
463
+ webview.WebCookieManager.clearAllCookiesSync(true);
464
+ webview.WebCookieManager.clearSessionCookieSync()
465
+ webview.WebStorage.deleteAllData();
466
+ }
467
+
468
+ setFraudulentWebsiteWarningEnabled(status: boolean) {
469
+ try {
470
+ this.controller.enableSafeBrowsing(status);
471
+ } catch (error) {
472
+ Logger.error(TAG, `[RNOH] setFraudulentWebsiteWarningEnabled Errorcode: ${error.code}`);
473
+ }
474
+ }
475
+
476
+ onDownloadStart(event: OnDownloadStartEvent) {
477
+ try {
478
+ this.eventEmitter!.emit('fileDownload', {
479
+ downloadUrl: event.url
480
+ })
481
+ } catch (error) {
482
+ Logger.error(TAG, `[RNOH] onDownloadStart Errorcode: ${error.code}`);
483
+ }
484
+ }
485
+
486
+ onRenderExited(event: OnRenderExitedEvent) {
487
+ try {
488
+
489
+ } catch (error) {
490
+ Logger.error(TAG, `[RNOH] onRenderExited Errorcode: ${error.code}`);
491
+ }
492
+ }
493
+
494
+ onTitleReceive(event: OnTitleReceiveEvent) {
495
+ try {
496
+
497
+ } catch (error) {
498
+ Logger.error(TAG, `[RNOH] onTitleReceive Errorcode: ${error.code}`);
499
+ }
500
+ }
501
+
502
+ customMenuSelection(menuItem: TextMenuItem, selectionText: string) {
503
+ try {
504
+ selectionText = JSON.parse(selectionText).selection;
505
+ this.eventEmitter!.emit('customMenuSelection', {
506
+ label: menuItem.content.toString(),
507
+ key: JSON.parse(JSON.stringify(menuItem.id)).id_,
508
+ selectedText: selectionText
509
+ })
510
+ } catch (error) {
511
+ Logger.error(TAG, `[RNOH] customMenuSelection Errorcode: ${error.code}`);
512
+ }
513
+ }
514
+ }