@react-native-ohos/react-native-webview 13.10.6-beta.3 → 13.10.6
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.
- package/CHANGELOG.md +16 -0
- package/LICENSE +21 -21
- package/README.md +385 -393
- package/harmony/rn_webview/.gitignore +6 -0
- package/harmony/rn_webview/BuildProfile.ets +1 -1
- package/harmony/rn_webview/LICENSE +21 -21
- package/harmony/rn_webview/NOTICE +33 -33
- package/harmony/rn_webview/OAT.xml +44 -44
- package/harmony/rn_webview/README.OpenSource +10 -10
- package/harmony/rn_webview/build-profile.json5 +28 -28
- package/harmony/rn_webview/index.ets +33 -33
- package/harmony/rn_webview/obfuscation-rules.txt +17 -17
- package/harmony/rn_webview/oh-package-lock.json5 +18 -18
- package/harmony/rn_webview/oh-package.json5 +13 -13
- package/harmony/rn_webview/src/main/cpp/CMakeLists.txt +9 -9
- package/harmony/rn_webview/src/main/cpp/WebViewPackage.h +36 -36
- package/harmony/rn_webview/src/main/cpp/generated/RNOH/generated/BaseReactNativeWebviewPackage.h +94 -94
- package/harmony/rn_webview/src/main/cpp/generated/RNOH/generated/components/RNCWebViewJSIBinder.h +129 -128
- package/harmony/rn_webview/src/main/cpp/generated/RNOH/generated/turbo_modules/RNCWebView.cpp +20 -20
- package/harmony/rn_webview/src/main/cpp/generated/RNOH/generated/turbo_modules/RNCWebView.h +16 -16
- package/harmony/rn_webview/src/main/cpp/generated/RNOH/generated/turbo_modules/RNCWebViewModule.cpp +19 -19
- package/harmony/rn_webview/src/main/cpp/generated/RNOH/generated/turbo_modules/RNCWebViewModule.h +16 -16
- package/harmony/rn_webview/src/main/cpp/generated/react/renderer/components/react_native_webview/ComponentDescriptors.h +22 -22
- package/harmony/rn_webview/src/main/cpp/generated/react/renderer/components/react_native_webview/EventEmitters.cpp +240 -240
- package/harmony/rn_webview/src/main/cpp/generated/react/renderer/components/react_native_webview/EventEmitters.h +285 -285
- package/harmony/rn_webview/src/main/cpp/generated/react/renderer/components/react_native_webview/Props.cpp +156 -155
- package/harmony/rn_webview/src/main/cpp/generated/react/renderer/components/react_native_webview/Props.h +340 -339
- package/harmony/rn_webview/src/main/cpp/generated/react/renderer/components/react_native_webview/ShadowNodes.cpp +19 -19
- package/harmony/rn_webview/src/main/cpp/generated/react/renderer/components/react_native_webview/ShadowNodes.h +34 -34
- package/harmony/rn_webview/src/main/cpp/generated/react/renderer/components/react_native_webview/States.cpp +16 -16
- package/harmony/rn_webview/src/main/cpp/generated/react/renderer/components/react_native_webview/States.h +19 -19
- package/harmony/rn_webview/src/main/ets/CutomReference.ts +49 -49
- package/harmony/rn_webview/src/main/ets/Logger.ts +63 -63
- package/harmony/rn_webview/src/main/ets/Magic.ets +223 -221
- package/harmony/rn_webview/src/main/ets/RNCWebView.ets +1098 -903
- package/harmony/rn_webview/src/main/ets/RNCWebViewPackage.ets +65 -65
- package/harmony/rn_webview/src/main/ets/ShouldRequestUrl.ts +67 -67
- package/harmony/rn_webview/src/main/ets/WebViewBaseOperate.ets +490 -490
- package/harmony/rn_webview/src/main/ets/WebViewTurboModule.ets +81 -81
- package/harmony/rn_webview/src/main/ets/generated/components/RNCWebView.ts +516 -511
- package/harmony/rn_webview/src/main/ets/generated/components/ts.ts +5 -5
- package/harmony/rn_webview/src/main/ets/generated/index.ets +5 -5
- package/harmony/rn_webview/src/main/ets/generated/ts.ts +6 -6
- package/harmony/rn_webview/src/main/ets/generated/turboModules/RNCWebView.ts +18 -18
- package/harmony/rn_webview/src/main/ets/generated/turboModules/RNCWebViewModule.ts +16 -16
- package/harmony/rn_webview/src/main/ets/generated/turboModules/ts.ts +6 -6
- package/harmony/rn_webview/src/main/module.json5 +10 -10
- package/harmony/rn_webview/src/main/resources/base/element/string.json +39 -39
- package/harmony/rn_webview/src/main/resources/en_US/element/string.json +39 -39
- package/harmony/rn_webview/src/main/resources/zh_CN/element/string.json +39 -39
- package/harmony/rn_webview/src/test/List.test.ets +4 -4
- package/harmony/rn_webview/src/test/LocalUnit.test.ets +32 -32
- package/harmony/rn_webview/ts.ets +28 -28
- package/harmony/rn_webview.har +0 -0
- package/package.json +105 -104
- package/src/NativeRNCWebView.ts +15 -15
- package/src/NativeRNCWebViewModule.ts +17 -17
- package/src/RNCWebViewNativeComponent.ts +289 -288
- package/src/WebView.harmony.tsx +331 -331
- package/src/WebView.tsx +4 -4
- package/src/codegenUtils.ts +8 -8
- package/src/index.ts +4 -4
|
@@ -1,904 +1,1099 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* MIT License
|
|
3
|
-
*
|
|
4
|
-
* Copyright (C) 2025 Huawei Device Co., Ltd.
|
|
5
|
-
*
|
|
6
|
-
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
-
* of this software and associated documentation files (the "Software"), to deal
|
|
8
|
-
* in the Software without restriction, including without limitation the rights
|
|
9
|
-
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
-
* copies of the Software, and to permit persons to whom the Software is
|
|
11
|
-
* furnished to do so, subject to the following conditions:
|
|
12
|
-
*
|
|
13
|
-
* The above copyright notice and this permission notice shall be included in all
|
|
14
|
-
* copies or substantial portions of the Software.
|
|
15
|
-
*
|
|
16
|
-
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
-
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
-
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
-
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
-
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
-
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
-
* SOFTWARE.
|
|
23
|
-
*/
|
|
24
|
-
|
|
25
|
-
import { RNComponentContext } from '@rnoh/react-native-openharmony';
|
|
26
|
-
import webview from '@ohos.web.webview';
|
|
27
|
-
import { url as OSUrl } from '@kit.ArkTS';
|
|
28
|
-
import { RNC, TM } from './generated';
|
|
29
|
-
import Logger from './Logger';
|
|
30
|
-
import { BaseOperate } from './WebViewBaseOperate';
|
|
31
|
-
import { deviceInfo } from '@kit.BasicServicesKit';
|
|
32
|
-
import {
|
|
33
|
-
AlertEvent,
|
|
34
|
-
CACHE_MODE,
|
|
35
|
-
JAVASCRIPT_INTERFACE,
|
|
36
|
-
ONE_HUNDRED,
|
|
37
|
-
EIGHT,
|
|
38
|
-
ResultType,
|
|
39
|
-
RNCWebViewBridge,
|
|
40
|
-
WebViewEventParams,
|
|
41
|
-
WebViewNewSource,
|
|
42
|
-
WebViewOverScrollMode,
|
|
43
|
-
ZERO,
|
|
44
|
-
COMMAND_NAME,
|
|
45
|
-
WebViewDescriptor,
|
|
46
|
-
REFRESH_OFFSET,
|
|
47
|
-
MINHEIGHT,
|
|
48
|
-
WebMediaCapturePermissionGrantType,
|
|
49
|
-
MenuItem
|
|
50
|
-
} from './Magic';
|
|
51
|
-
|
|
52
|
-
import { abilityAccessCtrl, bundleManager, Permissions } from '@kit.AbilityKit';
|
|
53
|
-
import { WebViewTurboModule, ShouldStartParams, ShouldOverrideCallbackState } from './WebViewTurboModule';
|
|
54
|
-
import { AnyThreadRNInstance, WorkerTaskRunnable } from '@rnoh/react-native-openharmony/src/main/ets/RNOH';
|
|
55
|
-
import buffer from '@ohos.buffer';
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
@State
|
|
108
|
-
@State
|
|
109
|
-
@State
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
private
|
|
113
|
-
private
|
|
114
|
-
private
|
|
115
|
-
private
|
|
116
|
-
private
|
|
117
|
-
private
|
|
118
|
-
|
|
119
|
-
private
|
|
120
|
-
static readonly
|
|
121
|
-
private
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
)
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
this.
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
this.
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
this.
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
this.
|
|
194
|
-
this.
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
value: this.resourceToString($r('app.string.
|
|
272
|
-
action: () => event.result.
|
|
273
|
-
},
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
this.webViewBaseOperate
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
this.
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
this.
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
this.
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
.
|
|
706
|
-
.
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
this.
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
1
|
+
/**
|
|
2
|
+
* MIT License
|
|
3
|
+
*
|
|
4
|
+
* Copyright (C) 2025 Huawei Device Co., Ltd.
|
|
5
|
+
*
|
|
6
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
* in the Software without restriction, including without limitation the rights
|
|
9
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
* copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
* furnished to do so, subject to the following conditions:
|
|
12
|
+
*
|
|
13
|
+
* The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
* copies or substantial portions of the Software.
|
|
15
|
+
*
|
|
16
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
* SOFTWARE.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
import { RNComponentContext } from '@rnoh/react-native-openharmony';
|
|
26
|
+
import webview from '@ohos.web.webview';
|
|
27
|
+
import { url as OSUrl } from '@kit.ArkTS';
|
|
28
|
+
import { RNC, TM } from './generated';
|
|
29
|
+
import Logger from './Logger';
|
|
30
|
+
import { BaseOperate } from './WebViewBaseOperate';
|
|
31
|
+
import { deviceInfo } from '@kit.BasicServicesKit';
|
|
32
|
+
import {
|
|
33
|
+
AlertEvent,
|
|
34
|
+
CACHE_MODE,
|
|
35
|
+
JAVASCRIPT_INTERFACE,
|
|
36
|
+
ONE_HUNDRED,
|
|
37
|
+
EIGHT,
|
|
38
|
+
ResultType,
|
|
39
|
+
RNCWebViewBridge,
|
|
40
|
+
WebViewEventParams,
|
|
41
|
+
WebViewNewSource,
|
|
42
|
+
WebViewOverScrollMode,
|
|
43
|
+
ZERO,
|
|
44
|
+
COMMAND_NAME,
|
|
45
|
+
WebViewDescriptor,
|
|
46
|
+
REFRESH_OFFSET,
|
|
47
|
+
MINHEIGHT,
|
|
48
|
+
WebMediaCapturePermissionGrantType,
|
|
49
|
+
MenuItem
|
|
50
|
+
} from './Magic';
|
|
51
|
+
|
|
52
|
+
import { abilityAccessCtrl, bundleManager, Permissions } from '@kit.AbilityKit';
|
|
53
|
+
import { WebViewTurboModule, ShouldStartParams, ShouldOverrideCallbackState } from './WebViewTurboModule';
|
|
54
|
+
import { AnyThreadRNInstance, WorkerTaskRunnable } from '@rnoh/react-native-openharmony/src/main/ets/RNOH';
|
|
55
|
+
import buffer from '@ohos.buffer';
|
|
56
|
+
import { window } from '@kit.ArkUI';
|
|
57
|
+
|
|
58
|
+
export const TAG = "WebView"
|
|
59
|
+
|
|
60
|
+
export const WEB_VIEW = "RNCWebView"
|
|
61
|
+
|
|
62
|
+
@Sendable
|
|
63
|
+
class WorkerRunnable implements WorkerTaskRunnable<ShouldStartParams> {
|
|
64
|
+
run(rnInstance: AnyThreadRNInstance, params: ShouldStartParams): void {
|
|
65
|
+
params.lockState = ShouldOverrideCallbackState.UNDECIDED
|
|
66
|
+
rnInstance.getTurboModule<WebViewTurboModule>(TM.RNCWebViewModule.NAME).setShouldStartParams(params)
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
@Component
|
|
71
|
+
export struct RNCWebView {
|
|
72
|
+
public static readonly NAME = RNC.RNCWebView.NAME
|
|
73
|
+
ctx!: RNComponentContext
|
|
74
|
+
tag: number = ZERO
|
|
75
|
+
source: WebViewNewSource = {
|
|
76
|
+
uri: "",
|
|
77
|
+
method: "",
|
|
78
|
+
body: "",
|
|
79
|
+
html: "",
|
|
80
|
+
baseUrl: ""
|
|
81
|
+
}
|
|
82
|
+
html: string | undefined = "";
|
|
83
|
+
url: string | Resource = "";
|
|
84
|
+
body: string | undefined = "";
|
|
85
|
+
controller: webview.WebviewController = new webview.WebviewController();
|
|
86
|
+
schemeHandler: webview.WebSchemeHandler = new webview.WebSchemeHandler();
|
|
87
|
+
javaScriptEnable: boolean = true;
|
|
88
|
+
allowFileAccess: boolean = true;
|
|
89
|
+
forceDark: boolean = true;
|
|
90
|
+
minFontSize: number = EIGHT;
|
|
91
|
+
overScrollMode: OverScrollMode = OverScrollMode.NEVER;
|
|
92
|
+
progress: number = ZERO;
|
|
93
|
+
cacheMode: number = CacheMode.Default;
|
|
94
|
+
requestUrl: string = "";
|
|
95
|
+
bundleName: string = "";
|
|
96
|
+
messagingEnabled: boolean = false;
|
|
97
|
+
hasRegisterJavaScriptProxy: boolean = false;
|
|
98
|
+
controllerAttached: boolean = false;
|
|
99
|
+
renderMode: RenderMode = RenderMode.SYNC_RENDER;
|
|
100
|
+
scrollEnabled = true;
|
|
101
|
+
@State nestedScroll: NestedScrollMode = NestedScrollMode.SELF_FIRST;
|
|
102
|
+
headers: Array<webview.WebHeader> = []
|
|
103
|
+
injectedJavaScriptBeforeContentLoaded: Array<ScriptItem> = [
|
|
104
|
+
{ script: '', scriptRules: ["*"] }
|
|
105
|
+
];
|
|
106
|
+
allowPageStartInProgress = true;
|
|
107
|
+
@State webviewWidth: number = ZERO
|
|
108
|
+
@State webviewHeight: number = ZERO
|
|
109
|
+
@State isRefreshing: boolean = false
|
|
110
|
+
@State isFullScreen: boolean = false
|
|
111
|
+
@State mode: MixedMode = MixedMode.All;
|
|
112
|
+
private unregisterDescriptorChangesListener?: () => void = undefined
|
|
113
|
+
private cleanupCommandCallback?: () => void = undefined
|
|
114
|
+
private eventEmitter: RNC.RNCWebView.EventEmitter | undefined = undefined
|
|
115
|
+
private cleanUpCallbacks: (() => void)[] = []
|
|
116
|
+
private descriptorWrapper: WebViewDescriptor = Object() as WebViewDescriptor
|
|
117
|
+
private webViewBaseOperate: BaseOperate | null = null
|
|
118
|
+
private shouldInterceptLoad: boolean = true
|
|
119
|
+
private callLoadTimer: number = -1
|
|
120
|
+
static readonly SHOULD_OVERRIDE_URL_LOADING_TIMEOUT: number = 250
|
|
121
|
+
private debounceTimer: number = -1
|
|
122
|
+
static readonly DEBOUNCE_TIME: number = 100
|
|
123
|
+
private isFirstDebounce: boolean = true
|
|
124
|
+
private initialOrientation: window.Orientation = window.Orientation.PORTRAIT
|
|
125
|
+
private isOrientationSaved: boolean = false
|
|
126
|
+
private cachedWindow: window.Window | null = null
|
|
127
|
+
private allowsFullscreenVideo: boolean = false
|
|
128
|
+
|
|
129
|
+
aboutToAppear() {
|
|
130
|
+
try {
|
|
131
|
+
this.initVariable()
|
|
132
|
+
this.saveInitialOrientation()
|
|
133
|
+
this.getBundleName()
|
|
134
|
+
this.url = this.source.uri as string;
|
|
135
|
+
this.onDescriptorWrapperChange(this.descriptorWrapper)
|
|
136
|
+
this.unregisterDescriptorChangesListener = this.ctx.descriptorRegistry.subscribeToDescriptorChanges(this.tag,
|
|
137
|
+
(newDescriptor) => {
|
|
138
|
+
this.onDescriptorWrapperChange(newDescriptor as WebViewDescriptor)
|
|
139
|
+
}
|
|
140
|
+
)
|
|
141
|
+
BaseOperate.setThirdPartyCookiesEnabled(this.descriptorWrapper.rawProps.thirdPartyCookiesEnabled)
|
|
142
|
+
webview.WebviewController.setWebDebuggingAccess(this.descriptorWrapper.rawProps.webviewDebuggingEnabled)
|
|
143
|
+
this.registerCommandCallback()
|
|
144
|
+
if (this.hasIncognito()) {
|
|
145
|
+
this.cacheMode = CacheMode.Online;
|
|
146
|
+
}
|
|
147
|
+
if (this.source.headers) {
|
|
148
|
+
this.source.headers.forEach(item => {
|
|
149
|
+
if (item.name && item.value) {
|
|
150
|
+
this.headers.push({ headerKey: item.name, headerValue: item.value })
|
|
151
|
+
}
|
|
152
|
+
})
|
|
153
|
+
}
|
|
154
|
+
} catch (error) {
|
|
155
|
+
Logger.error(TAG, `[RNOH]Errorcode: ${error.code}, Message: ${error.message}`);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
hasIncognito(): boolean {
|
|
161
|
+
return this.descriptorWrapper.rawProps.incognito && this.descriptorWrapper.rawProps.incognito === true
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
createWebViewEvent(type: string): WebViewEventParams {
|
|
165
|
+
return this.webViewBaseOperate?.createWebViewEvent({ type, progress: this.progress }) as WebViewEventParams;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
aboutToDisappear() {
|
|
169
|
+
// 恢复初始屏幕方向和沉浸式状态,防止全屏状态下组件销毁后状态残留
|
|
170
|
+
// 无论是否在全屏状态,都尝试恢复窗口状态(handleFullScreenEnter 异步操作可能在组件销毁后才完成)
|
|
171
|
+
if (this.cachedWindow) {
|
|
172
|
+
try {
|
|
173
|
+
this.cachedWindow.setPreferredOrientation(this.initialOrientation);
|
|
174
|
+
this.cachedWindow.setWindowLayoutFullScreen(false);
|
|
175
|
+
this.cachedWindow.setWindowSystemBarEnable(['status', 'navigation']);
|
|
176
|
+
Logger.debug(TAG, '[WebViewFullScreen] Restored window state in aboutToDisappear');
|
|
177
|
+
} catch (error) {
|
|
178
|
+
Logger.error(TAG, `[WebViewFullScreen] Failed to restore in aboutToDisappear: ${error.code}`);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
this.isFullScreen = false;
|
|
182
|
+
this.cachedWindow = null;
|
|
183
|
+
this.getUIContext().getFocusController().clearFocus()
|
|
184
|
+
this.cleanupCommandCallback?.()
|
|
185
|
+
this.unregisterDescriptorChangesListener?.()
|
|
186
|
+
this.cleanUpCallbacks.forEach(cb => cb())
|
|
187
|
+
try {
|
|
188
|
+
if (this.hasIncognito()) {
|
|
189
|
+
this.webViewBaseOperate?.setIncognito()
|
|
190
|
+
}
|
|
191
|
+
this.controller.deleteJavaScriptRegister(JAVASCRIPT_INTERFACE)
|
|
192
|
+
this.controller.refresh()
|
|
193
|
+
this.hasRegisterJavaScriptProxy = false
|
|
194
|
+
this.webViewBaseOperate = null
|
|
195
|
+
} catch (error) {
|
|
196
|
+
Logger.error(TAG, `[RNOH]Errorcode: ${error.code}, Message: ${error.message}`);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
registerCommandCallback() {
|
|
201
|
+
this.cleanupCommandCallback = this.ctx.componentCommandReceiver.registerCommandCallback(
|
|
202
|
+
this.tag,
|
|
203
|
+
(command: COMMAND_NAME, args: string[]) => this.webViewBaseOperate?.registerCommandCallback(command, args));
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
onLoadingStart() {
|
|
207
|
+
this.webViewBaseOperate?.emitLoadingStart({ progress: this.progress })
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
onProgressChange(event: OnProgressChangeEvent) {
|
|
211
|
+
this.progress = event.newProgress
|
|
212
|
+
// 修复单页面应用切换路由时 onPageBegin 未触发的问题
|
|
213
|
+
if (this.controller.getUrl() !== this.url && this.progress < ONE_HUNDRED && this.allowPageStartInProgress) {
|
|
214
|
+
this.allowPageStartInProgress = false;
|
|
215
|
+
this.onLoadingStart();
|
|
216
|
+
}
|
|
217
|
+
this.webViewBaseOperate?.emitProgressChange({ progress: this.progress })
|
|
218
|
+
if (this.progress === ONE_HUNDRED) {
|
|
219
|
+
this.allowPageStartInProgress = true;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
onLoadingFinish() {
|
|
224
|
+
this.webViewBaseOperate?.emitLoadingFinish({ progress: this.progress })
|
|
225
|
+
this.isRefreshing = false
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
runInjectedJavaScript() {
|
|
229
|
+
let injectedJS = this.descriptorWrapper.rawProps.injectedJavaScript
|
|
230
|
+
if (this.javaScriptEnable && injectedJS != "" && this.controllerAttached) {
|
|
231
|
+
try {
|
|
232
|
+
this.controller.runJavaScript("(function() {\n" + injectedJS + ";\n})();")
|
|
233
|
+
.then((result) => {
|
|
234
|
+
Logger.debug(TAG, '[RNOH] result: ' + result);
|
|
235
|
+
})
|
|
236
|
+
.catch((error: string | Error) => {
|
|
237
|
+
Logger.error(TAG, "[RNOH] error: " + error);
|
|
238
|
+
})
|
|
239
|
+
} catch (error) {
|
|
240
|
+
Logger.error(TAG, `[RNOH]Errorcode: ${error.code}, Message: ${error.message}`);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
getJsDialogTitle() {
|
|
246
|
+
const url = this.controller.getUrl()
|
|
247
|
+
// 对于 data: URL,只显示 'JavaScript',类似于 Chrome
|
|
248
|
+
let title = 'JavaScript';
|
|
249
|
+
const isDataUrl = (url !== null) && url.startsWith("data:");
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
if (!isDataUrl) {
|
|
253
|
+
try {
|
|
254
|
+
const dialogUrl = OSUrl.URL.parseURL(url);
|
|
255
|
+
title = `网址为”${dialogUrl.protocol}//${dialogUrl.host}“的网页显示:`;
|
|
256
|
+
} catch (ex) {
|
|
257
|
+
title = url;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
return title;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
onJavascriptAlert(event?: AlertEvent) {
|
|
265
|
+
if (event) {
|
|
266
|
+
AlertDialog.show({
|
|
267
|
+
title: this.getJsDialogTitle(),
|
|
268
|
+
message: event.message,
|
|
269
|
+
alignment: DialogAlignment.Center,
|
|
270
|
+
secondaryButton: {
|
|
271
|
+
value: this.resourceToString($r('app.string.determined')),
|
|
272
|
+
action: () => event.result.handleConfirm()
|
|
273
|
+
},
|
|
274
|
+
cancel: () => event.result.handleCancel(),
|
|
275
|
+
})
|
|
276
|
+
}
|
|
277
|
+
return true
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
onJavascriptConfirm(event?: AlertEvent) {
|
|
281
|
+
if (event) {
|
|
282
|
+
AlertDialog.show({
|
|
283
|
+
title: this.getJsDialogTitle(),
|
|
284
|
+
message: event.message,
|
|
285
|
+
alignment: DialogAlignment.Center,
|
|
286
|
+
secondaryButton: {
|
|
287
|
+
value: this.resourceToString($r('app.string.determined')),
|
|
288
|
+
action: () => event.result.handleConfirm()
|
|
289
|
+
},
|
|
290
|
+
cancel: () => event.result.handleCancel(),
|
|
291
|
+
primaryButton: {
|
|
292
|
+
value: this.resourceToString($r('app.string.cancel')),
|
|
293
|
+
action: () => event.result.handleCancel()
|
|
294
|
+
},
|
|
295
|
+
})
|
|
296
|
+
}
|
|
297
|
+
return true
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
ignoreSilentHardwareSwitchMethods(ignoreSilentHardwareSwitch: boolean) {
|
|
301
|
+
this.webViewBaseOperate?.ignoreSilentHardwareSwitchMethods(ignoreSilentHardwareSwitch)
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
loadHtmlData(html: string = '', url: string = '') {
|
|
305
|
+
try {
|
|
306
|
+
this.controller.loadData(
|
|
307
|
+
html,
|
|
308
|
+
"text/html",
|
|
309
|
+
"UTF-8",
|
|
310
|
+
url,
|
|
311
|
+
" "
|
|
312
|
+
);
|
|
313
|
+
} catch (error) {
|
|
314
|
+
Logger.error(TAG, "error:" + error)
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
controllerAttachedInit(): void {
|
|
319
|
+
this.controllerAttached = true;
|
|
320
|
+
this.eventEmitter = new RNC.RNCWebView.EventEmitter(this.ctx.rnInstance, this.tag)
|
|
321
|
+
this.webViewBaseOperate = new BaseOperate(this.eventEmitter, this.controller)
|
|
322
|
+
this.webViewBaseOperate.setCustomUserAgent(this.descriptorWrapper.rawProps.userAgent,
|
|
323
|
+
this.descriptorWrapper.rawProps.applicationNameForUserAgent)
|
|
324
|
+
this.webViewBaseOperate.setFraudulentWebsiteWarningEnabled(this.descriptorWrapper.rawProps.fraudulentWebsiteWarningEnabled)
|
|
325
|
+
|
|
326
|
+
let schemeList = this.descriptorWrapper.rawProps.schemeList
|
|
327
|
+
if(schemeList?.length){
|
|
328
|
+
schemeList.forEach(scheme=>{
|
|
329
|
+
this.schemeHandler.onRequestStart((request: webview.WebSchemeHandlerRequest, resourceHandler: webview.WebResourceHandler) => {
|
|
330
|
+
console.log("[schemeHandler] onRequestStart");
|
|
331
|
+
return true;
|
|
332
|
+
})
|
|
333
|
+
this.schemeHandler.onRequestStop((request: webview.WebSchemeHandlerRequest) => {
|
|
334
|
+
console.log("[schemeHandler] onRequestStop");
|
|
335
|
+
});
|
|
336
|
+
this.controller.setWebSchemeHandler(scheme, this.schemeHandler);
|
|
337
|
+
})
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
if (!this.hasRegisterJavaScriptProxy && this.descriptorWrapper.rawProps.messagingEnabled) {
|
|
341
|
+
this.registerJavaScriptProxyOnly()
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
let baseUrl = this.source.baseUrl
|
|
345
|
+
let uri = this.source.uri
|
|
346
|
+
if (this.source.html != undefined && this.source.html != "") {
|
|
347
|
+
this.loadHtmlData(this.source.html, baseUrl)
|
|
348
|
+
} else if (uri != undefined && uri != "") {
|
|
349
|
+
if (this.source.method && this.source.method.toUpperCase() === 'POST' && this.source.body) {
|
|
350
|
+
let postData = buffer.from(this.source.body);
|
|
351
|
+
let url = uri as string;
|
|
352
|
+
this.controller.postUrl(url, postData?.buffer);
|
|
353
|
+
} else {
|
|
354
|
+
this.controller.loadUrl(uri, this.headers);
|
|
355
|
+
}
|
|
356
|
+
} else {
|
|
357
|
+
this.loadHtmlData()
|
|
358
|
+
}
|
|
359
|
+
if (!this.hasRegisterJavaScriptProxy) {
|
|
360
|
+
this.registerPostMessage()
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
onPageBegin() {
|
|
365
|
+
try {
|
|
366
|
+
if (this.controller.getUrl() === this.url) {
|
|
367
|
+
this.onLoadingStart();
|
|
368
|
+
}
|
|
369
|
+
this.controller.setScrollable(this.scrollEnabled)
|
|
370
|
+
this.ignoreSilentHardwareSwitchMethods(this.descriptorWrapper.rawProps.ignoreSilentHardwareSwitch)
|
|
371
|
+
} catch (error) {
|
|
372
|
+
Logger.debug(TAG,
|
|
373
|
+
`[RNOH] setignoreSilentHardwareSwitch and setScrollable ErrorCode: ${error.code}, Message: ${error.message}, userAgent: ${this.descriptorWrapper.rawProps.userAgent}`);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
getBundleName() {
|
|
378
|
+
let bundleFlags =
|
|
379
|
+
bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_HAP_MODULE | bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_ABILITY |
|
|
380
|
+
bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_REQUESTED_PERMISSION;
|
|
381
|
+
|
|
382
|
+
try {
|
|
383
|
+
bundleManager.getBundleInfoForSelf(bundleFlags, (error, data) => {
|
|
384
|
+
if (error) {
|
|
385
|
+
Logger.error(TAG,
|
|
386
|
+
`[RNOH] getBundleInfoForSelf failed ErrorCode: ${error.code}, Message: ${error.message}`);
|
|
387
|
+
} else {
|
|
388
|
+
this.bundleName = JSON.stringify(data.name)
|
|
389
|
+
}
|
|
390
|
+
});
|
|
391
|
+
} catch (error) {
|
|
392
|
+
Logger.error(TAG,
|
|
393
|
+
`[RNOH] getBundleInfoForSelf failed ErrorCode: ${error.code}, Message: ${error.message}`);
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
resourceToString(resource: Resource): string {
|
|
398
|
+
return getContext(this).resourceManager.getStringSync(resource)
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
onLoadFinished() {
|
|
402
|
+
this.onLoadingFinish()
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
onPageEndExecuteRunInjectedJavaScript(){
|
|
406
|
+
this.runInjectedJavaScript()
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
onPageEnd() {
|
|
410
|
+
this.runInjectedJavaScript()
|
|
411
|
+
this.onLoadingFinish()
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
getPermissionDialogMessage(event: OnPermissionRequestEvent) {
|
|
415
|
+
let permissionDialogMessage = ''
|
|
416
|
+
permissionDialogMessage = event.request.getAccessibleResource().toString()
|
|
417
|
+
switch (permissionDialogMessage) {
|
|
418
|
+
case ProtectedResourceType.VIDEO_CAPTURE:
|
|
419
|
+
permissionDialogMessage = this.resourceToString($r('app.string.use_your_camera'))
|
|
420
|
+
break;
|
|
421
|
+
case ProtectedResourceType.AUDIO_CAPTURE:
|
|
422
|
+
permissionDialogMessage = this.resourceToString($r('app.string.use_your_microphone'))
|
|
423
|
+
break;
|
|
424
|
+
case ProtectedResourceType.MidiSysex:
|
|
425
|
+
permissionDialogMessage = this.resourceToString($r('app.string.midi_sysex_resources'))
|
|
426
|
+
break;
|
|
427
|
+
case ProtectedResourceType.VIDEO_CAPTURE + "," + ProtectedResourceType.AUDIO_CAPTURE:
|
|
428
|
+
permissionDialogMessage = this.resourceToString($r('app.string.use_your_camera_and_microphone'))
|
|
429
|
+
break;
|
|
430
|
+
}
|
|
431
|
+
return permissionDialogMessage;
|
|
432
|
+
}
|
|
433
|
+
originWhitelistToRegex(originWhitelist: string): string {
|
|
434
|
+
const matchOperatorsRegex = /[|\\{}()[\]^$+*?.-]/g;
|
|
435
|
+
return `^${originWhitelist.replace(matchOperatorsRegex, '\\$&').replace(/\\\*/g, '.*')}`;
|
|
436
|
+
}
|
|
437
|
+
extractOrigin(url: string): string {
|
|
438
|
+
const result = /^[A-Za-z][A-Za-z0-9+\-.]+:(\/\/)?[^/]*/.exec(url);
|
|
439
|
+
return result === null ? '' : result[0];
|
|
440
|
+
};
|
|
441
|
+
passesWhitelist(compiledWhitelist: string[], url: string) {
|
|
442
|
+
const origin = this.extractOrigin(url);
|
|
443
|
+
return compiledWhitelist.some((x) => new RegExp(x).test(origin));
|
|
444
|
+
};
|
|
445
|
+
compileWhitelist(originWhitelist: string[]): string[] {
|
|
446
|
+
return ['about:blank', ...(originWhitelist || [])].map(this.originWhitelistToRegex);
|
|
447
|
+
}
|
|
448
|
+
onLoadIntercept(event: OnLoadInterceptEvent): boolean {
|
|
449
|
+
Logger.debug(TAG, `onLoadIntercept start`)
|
|
450
|
+
let originWhitelistArr = this.descriptorWrapper.rawProps.originWhitelist;
|
|
451
|
+
let hasOnShouldStartLoadWithRequestEventBool = this.descriptorWrapper.rawProps.hasOnShouldStartLoadWithRequestEvent
|
|
452
|
+
let urlString =
|
|
453
|
+
this.webViewBaseOperate?.verifyURLFormat(event.data.getRequestUrl(), this.source.html, this.source.baseUrl) || "";
|
|
454
|
+
|
|
455
|
+
if (this.passesWhitelist(this.compileWhitelist(originWhitelistArr), urlString) &&
|
|
456
|
+
!hasOnShouldStartLoadWithRequestEventBool) {
|
|
457
|
+
return false
|
|
458
|
+
}
|
|
459
|
+
this.webViewBaseOperate?.setLockIdentifier(BaseOperate.generateLockIdentifier())
|
|
460
|
+
|
|
461
|
+
const params = new ShouldStartParams();
|
|
462
|
+
params.lockIdentifier = this.webViewBaseOperate?.getLockIdentifier() || -1
|
|
463
|
+
this.ctx.runOnWorkerThread(new WorkerRunnable(), params);
|
|
464
|
+
this.webViewBaseOperate?.emitShouldStartLoadWithRequest(event, this.source.html, this.source.baseUrl)
|
|
465
|
+
const startTime = Date.now();
|
|
466
|
+
// 当lockState没变化并且小于超时时间,阻塞进程
|
|
467
|
+
while (params.lockState === ShouldOverrideCallbackState.UNDECIDED &&
|
|
468
|
+
Date.now() - startTime < RNCWebView.SHOULD_OVERRIDE_URL_LOADING_TIMEOUT) {
|
|
469
|
+
// 空循环等待
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
Logger.debug('params.lockState res:' + params.lockState + `, wait time is ${Date.now() - startTime}`);
|
|
473
|
+
return params.lockState === ShouldOverrideCallbackState.SHOULD_OVERRIDE;
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
onOverrideUrlLoading(event: WebResourceRequest) {
|
|
477
|
+
this.webViewBaseOperate?.emitShouldStartLoadWithRequestOverrideUrlLoading(event)
|
|
478
|
+
return false
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
onCreateMenu = (menuItems: Array<TextMenuItem>) => {
|
|
482
|
+
let customMenuItems = this.descriptorWrapper.rawProps.menuItems
|
|
483
|
+
if (customMenuItems == undefined) {
|
|
484
|
+
return menuItems;
|
|
485
|
+
} else if (customMenuItems.length == 0) {
|
|
486
|
+
return [];
|
|
487
|
+
} else {
|
|
488
|
+
let menuItemsArray: Array<TextMenuItem> = [];
|
|
489
|
+
for (let index = 0; index < customMenuItems.length; index++) {
|
|
490
|
+
let element: MenuItem = customMenuItems[index];
|
|
491
|
+
let customItem: TextMenuItem = {
|
|
492
|
+
content: element.label,
|
|
493
|
+
id: TextMenuItemId.of(element.key)
|
|
494
|
+
};
|
|
495
|
+
menuItemsArray.push(customItem)
|
|
496
|
+
}
|
|
497
|
+
return menuItemsArray;
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
onMenuItemClick(menuItem: TextMenuItem): boolean {
|
|
502
|
+
if (this.descriptorWrapper.rawProps.menuItems != undefined) {
|
|
503
|
+
this.controller.runJavaScript("(function(){return {selection: window.getSelection().toString()} })()")
|
|
504
|
+
.then((result: string) => {
|
|
505
|
+
this.webViewBaseOperate?.customMenuSelection(menuItem, result)
|
|
506
|
+
})
|
|
507
|
+
.catch((error: string | Error) => {
|
|
508
|
+
Logger.info('[RNOH] function onMenuItemClick error: ' + error);
|
|
509
|
+
})
|
|
510
|
+
// 禁用系统默认行为
|
|
511
|
+
return true;
|
|
512
|
+
}
|
|
513
|
+
return false;
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
onPermissionRequestAlert(event: OnPermissionRequestEvent){
|
|
517
|
+
AlertDialog.show({
|
|
518
|
+
title: this.resourceToString($r('app.string.on_confirm')) + event.request.getOrigin(),
|
|
519
|
+
message: this.getPermissionDialogMessage(event),
|
|
520
|
+
alignment: DialogAlignment.Center,
|
|
521
|
+
primaryButton: {
|
|
522
|
+
value: $r('app.string.deny'),
|
|
523
|
+
action: () => {
|
|
524
|
+
event.request.deny();
|
|
525
|
+
}
|
|
526
|
+
},
|
|
527
|
+
secondaryButton: {
|
|
528
|
+
value: $r('app.string.on_confirm'),
|
|
529
|
+
action: () => {
|
|
530
|
+
event.request.grant(event.request.getAccessibleResource());
|
|
531
|
+
}
|
|
532
|
+
},
|
|
533
|
+
cancel: () => {
|
|
534
|
+
event.request.deny();
|
|
535
|
+
}
|
|
536
|
+
})
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
async handleMediaCapturePermissionGrantType(resources: string[], domain: string) {
|
|
540
|
+
let permissionList: Array<Permissions> = [];
|
|
541
|
+
resources.forEach(resource => {
|
|
542
|
+
switch (resource.toString()) {
|
|
543
|
+
case 'TYPE_VIDEO_CAPTURE':
|
|
544
|
+
permissionList.push('ohos.permission.CAMERA');
|
|
545
|
+
break;
|
|
546
|
+
case 'TYPE_AUDIO_CAPTURE':
|
|
547
|
+
permissionList.push('ohos.permission.MICROPHONE');
|
|
548
|
+
break;
|
|
549
|
+
}
|
|
550
|
+
});
|
|
551
|
+
|
|
552
|
+
let atManager = abilityAccessCtrl.createAtManager();
|
|
553
|
+
await atManager.requestPermissionsFromUser(this.ctx.uiAbilityContext, permissionList);
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
private async getWindow(): Promise<window.Window | null> {
|
|
557
|
+
try {
|
|
558
|
+
const win = await window.getLastWindow(getContext(this));
|
|
559
|
+
if (win) {
|
|
560
|
+
this.cachedWindow = win;
|
|
561
|
+
}
|
|
562
|
+
return win;
|
|
563
|
+
} catch (error) {
|
|
564
|
+
console.error(TAG, `[WebViewFullScreenTest] getWindow Errorcode: ${error.code}`);
|
|
565
|
+
return null;
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
private async saveInitialOrientation() {
|
|
570
|
+
const win = await this.getWindow();
|
|
571
|
+
if (win) {
|
|
572
|
+
try {
|
|
573
|
+
const orientation = win.getPreferredOrientation();
|
|
574
|
+
this.initialOrientation = orientation;
|
|
575
|
+
this.isOrientationSaved = true;
|
|
576
|
+
console.debug(TAG, `[WebViewFullScreenTest] Saved initial orientation: ${orientation}`);
|
|
577
|
+
} catch (error) {
|
|
578
|
+
console.error(TAG, `[WebViewFullScreenTest] saveInitialOrientation Errorcode: ${error.code}`);
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
private async setOrientation(orientation: window.Orientation): Promise<boolean> {
|
|
584
|
+
const win = await this.getWindow();
|
|
585
|
+
if (win) {
|
|
586
|
+
try {
|
|
587
|
+
await win.setPreferredOrientation(orientation);
|
|
588
|
+
console.debug(TAG, `[WebViewFullScreenTest] Set orientation to: ${orientation}`);
|
|
589
|
+
return true;
|
|
590
|
+
} catch (error) {
|
|
591
|
+
console.error(TAG, `[WebViewFullScreenTest] setOrientation Errorcode: ${error.code}`);
|
|
592
|
+
return false;
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
return false;
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
// 处理全屏进入(带状态保护和异步串行)
|
|
599
|
+
private async handleFullScreenEnter() {
|
|
600
|
+
if (this.isFullScreen) {
|
|
601
|
+
Logger.debug(TAG, '[WebViewFullScreen] Already in full screen, skipping');
|
|
602
|
+
return;
|
|
603
|
+
}
|
|
604
|
+
if (!this.isOrientationSaved) {
|
|
605
|
+
Logger.warn(TAG, '[WebViewFullScreen] Initial orientation not saved yet, skipping full screen enter');
|
|
606
|
+
return;
|
|
607
|
+
}
|
|
608
|
+
try {
|
|
609
|
+
// 阶段1:设置方向
|
|
610
|
+
const orientationResult = await this.setOrientation(window.Orientation.AUTO_ROTATION);
|
|
611
|
+
if (!orientationResult) {
|
|
612
|
+
Logger.error(TAG, '[WebViewFullScreen] Failed to set orientation, aborting full screen enter');
|
|
613
|
+
return;
|
|
614
|
+
}
|
|
615
|
+
// 阶段2:设置沉浸式模式
|
|
616
|
+
const immersiveResult = await this.enterImmersiveMode();
|
|
617
|
+
if (!immersiveResult) {
|
|
618
|
+
Logger.error(TAG, '[WebViewFullScreen] Failed to enter immersive mode, rolling back');
|
|
619
|
+
// 回滚沉浸式模式(即使部分失败也要尝试恢复)
|
|
620
|
+
await this.exitImmersiveMode();
|
|
621
|
+
// 回滚方向设置
|
|
622
|
+
await this.setOrientation(this.initialOrientation);
|
|
623
|
+
return;
|
|
624
|
+
}
|
|
625
|
+
// 阶段3:所有操作成功,设置状态
|
|
626
|
+
this.isFullScreen = true;
|
|
627
|
+
} catch (error) {
|
|
628
|
+
Logger.error(TAG, `[WebViewFullScreen] Enter full screen failed: ${error}`);
|
|
629
|
+
// 异常时回滚所有操作
|
|
630
|
+
await this.exitImmersiveMode();
|
|
631
|
+
await this.setOrientation(this.initialOrientation);
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
// 处理全屏退出(带状态保护和异步串行)
|
|
636
|
+
private async handleFullScreenExit() {
|
|
637
|
+
if (!this.isFullScreen) {
|
|
638
|
+
Logger.debug(TAG, '[WebViewFullScreen] Not in full screen, skipping');
|
|
639
|
+
return;
|
|
640
|
+
}
|
|
641
|
+
try {
|
|
642
|
+
// 阶段1:恢复方向
|
|
643
|
+
const orientationResult = await this.setOrientation(this.initialOrientation);
|
|
644
|
+
if (!orientationResult) {
|
|
645
|
+
Logger.error(TAG, '[WebViewFullScreen] Failed to restore orientation, keeping full screen state');
|
|
646
|
+
return;
|
|
647
|
+
}
|
|
648
|
+
// 方向已恢复,清除 isFullScreen 让 UI 恢复原始布局
|
|
649
|
+
this.isFullScreen = false;
|
|
650
|
+
// 阶段2:退出沉浸式模式
|
|
651
|
+
const immersiveResult = await this.exitImmersiveMode();
|
|
652
|
+
if (!immersiveResult) {
|
|
653
|
+
Logger.error(TAG, '[WebViewFullScreen] Failed to exit immersive mode after restoring orientation');
|
|
654
|
+
// 沉浸式模式退出失败,但方向已恢复,isFullScreen 已清除,避免重复触发循环
|
|
655
|
+
}
|
|
656
|
+
} catch (error) {
|
|
657
|
+
Logger.error(TAG, `[WebViewFullScreen] Exit full screen failed: ${error}`);
|
|
658
|
+
// 异常时也应清除状态,避免卡死
|
|
659
|
+
this.isFullScreen = false;
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
// 进入沉浸式全屏模式(隐藏系统栏)
|
|
664
|
+
private async enterImmersiveMode(): Promise<boolean> {
|
|
665
|
+
const win = await this.getWindow();
|
|
666
|
+
if (win) {
|
|
667
|
+
try {
|
|
668
|
+
// 设置窗口为全屏布局模式,内容延伸到系统栏下方
|
|
669
|
+
await win.setWindowLayoutFullScreen(true);
|
|
670
|
+
// 隐藏系统导航栏和状态栏
|
|
671
|
+
await win.setWindowSystemBarEnable([]);
|
|
672
|
+
Logger.debug(TAG, '[WebViewFullScreen] Entered immersive mode');
|
|
673
|
+
return true;
|
|
674
|
+
} catch (error) {
|
|
675
|
+
console.error(TAG, `[WebViewFullScreen] enterImmersiveMode Errorcode: ${error.code}`);
|
|
676
|
+
return false;
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
return false;
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
// 退出沉浸式全屏模式(恢复系统栏)
|
|
683
|
+
private async exitImmersiveMode(): Promise<boolean> {
|
|
684
|
+
const win = await this.getWindow();
|
|
685
|
+
if (win) {
|
|
686
|
+
try {
|
|
687
|
+
// 关闭全屏布局模式
|
|
688
|
+
await win.setWindowLayoutFullScreen(false);
|
|
689
|
+
// 恢复显示系统导航栏和状态栏(默认显示所有系统栏)
|
|
690
|
+
await win.setWindowSystemBarEnable(['status', 'navigation']);
|
|
691
|
+
Logger.debug(TAG, '[WebViewFullScreen] Exited immersive mode');
|
|
692
|
+
return true;
|
|
693
|
+
} catch (error) {
|
|
694
|
+
console.error(TAG, `[WebViewFullScreen] exitImmersiveMode Errorcode: ${error.code}`);
|
|
695
|
+
return false;
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
return false;
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
build() {
|
|
702
|
+
Stack() {
|
|
703
|
+
if ( deviceInfo.sdkApiVersion >= 20) {
|
|
704
|
+
Web({ src: "", controller: this.controller, renderMode: this.renderMode })
|
|
705
|
+
.mixedMode(this.mode)
|
|
706
|
+
.onPermissionRequest(async (event: OnPermissionRequestEvent) => {
|
|
707
|
+
if (event && (this.getPermissionDialogMessage(event) != "TYPE_SENSOR")) {
|
|
708
|
+
const resources: string[] = event.request.getAccessibleResource();
|
|
709
|
+
if (resources.indexOf('TYPE_AUDIO_CAPTURE') >= 0 || resources.indexOf('TYPE_VIDEO_CAPTURE') >= 0 ) {
|
|
710
|
+
const originUrl = this.webViewBaseOperate?.verifyURLFormat(event.request.getOrigin(), this.source.html,
|
|
711
|
+
this.source.baseUrl);
|
|
712
|
+
const currentUrl = this.webViewBaseOperate?.verifyURLFormat(this.controller.getUrl(), this.source.html,
|
|
713
|
+
this.source.baseUrl);
|
|
714
|
+
const originDomain: string = OSUrl.URL.parseURL(originUrl).hostname;
|
|
715
|
+
const currentDomain: string = OSUrl.URL.parseURL(currentUrl).hostname;
|
|
716
|
+
let mediaCapturePermissionGrantType: string = WebMediaCapturePermissionGrantType.PROMPT
|
|
717
|
+
if (this.descriptorWrapper.rawProps.mediaCapturePermissionGrantType != undefined) {
|
|
718
|
+
mediaCapturePermissionGrantType = this.descriptorWrapper.rawProps.mediaCapturePermissionGrantType;
|
|
719
|
+
}
|
|
720
|
+
if (mediaCapturePermissionGrantType != WebMediaCapturePermissionGrantType.DENY) {
|
|
721
|
+
await this.handleMediaCapturePermissionGrantType(resources, originDomain)
|
|
722
|
+
}
|
|
723
|
+
switch (mediaCapturePermissionGrantType) {
|
|
724
|
+
case WebMediaCapturePermissionGrantType.GRANT_IF_SAME_HOST_ELSE_PROMPT:
|
|
725
|
+
if (originDomain != currentDomain) {
|
|
726
|
+
this.onPermissionRequestAlert(event)
|
|
727
|
+
} else {
|
|
728
|
+
event.request.grant(resources);
|
|
729
|
+
}
|
|
730
|
+
break;
|
|
731
|
+
case WebMediaCapturePermissionGrantType.GRANT_IF_SAME_HOST_ELSE_DENY:
|
|
732
|
+
if (originDomain != currentDomain) {
|
|
733
|
+
event.request.deny();
|
|
734
|
+
} else {
|
|
735
|
+
event.request.grant(resources);
|
|
736
|
+
}
|
|
737
|
+
break;
|
|
738
|
+
case WebMediaCapturePermissionGrantType.DENY:
|
|
739
|
+
event.request.deny();
|
|
740
|
+
break;
|
|
741
|
+
case WebMediaCapturePermissionGrantType.GRANT:
|
|
742
|
+
event.request.grant(resources);
|
|
743
|
+
break;
|
|
744
|
+
case WebMediaCapturePermissionGrantType.PROMPT:
|
|
745
|
+
this.onPermissionRequestAlert(event)
|
|
746
|
+
break;
|
|
747
|
+
}
|
|
748
|
+
} else {
|
|
749
|
+
this.onPermissionRequestAlert(event)
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
})
|
|
753
|
+
.width(this.isFullScreen ? "100%" : this.webviewWidth)
|
|
754
|
+
.height(this.isFullScreen ? "100%" : this.webviewHeight)
|
|
755
|
+
.fileAccess(this.allowFileAccess)
|
|
756
|
+
.constraintSize({ minHeight: MINHEIGHT })
|
|
757
|
+
.overScrollMode(this.overScrollMode)
|
|
758
|
+
.javaScriptAccess(this.javaScriptEnable)
|
|
759
|
+
.javaScriptOnDocumentStart(this.injectedJavaScriptBeforeContentLoaded)
|
|
760
|
+
.horizontalScrollBarAccess(this.descriptorWrapper.rawProps.showsHorizontalScrollIndicator)
|
|
761
|
+
.verticalScrollBarAccess(this.descriptorWrapper.rawProps.showsVerticalScrollIndicator)
|
|
762
|
+
.overviewModeAccess(this.descriptorWrapper.rawProps.scalesPageToFit)
|
|
763
|
+
.textZoomRatio(this.descriptorWrapper.rawProps.textZoom)
|
|
764
|
+
.backgroundColor(BaseOperate.getColorMode(this.ctx.uiAbilityContext,
|
|
765
|
+
this.descriptorWrapper.rawProps.forceDarkOn) === WebDarkMode.On ? Color.Black : Color.Transparent)
|
|
766
|
+
.darkMode(BaseOperate.getColorMode(this.ctx.uiAbilityContext, this.descriptorWrapper.rawProps.forceDarkOn))
|
|
767
|
+
.forceDarkAccess(this.forceDark)
|
|
768
|
+
.cacheMode(this.cacheMode)
|
|
769
|
+
.minFontSize(this.minFontSize)
|
|
770
|
+
.domStorageAccess(this.descriptorWrapper.rawProps.domStorageEnabled)
|
|
771
|
+
.zoomAccess(this.descriptorWrapper.rawProps.scalesPageToFit)
|
|
772
|
+
.overScrollMode(this.overScrollMode)
|
|
773
|
+
.onProgressChange((event: OnProgressChangeEvent) => this.onProgressChange(event))
|
|
774
|
+
.onScroll((event: OnScrollEvent) => this.webViewBaseOperate?.emitScroll(event))
|
|
775
|
+
.nestedScroll({
|
|
776
|
+
scrollForward: this.nestedScroll,
|
|
777
|
+
scrollBackward: this.nestedScroll,
|
|
778
|
+
})
|
|
779
|
+
.onLoadStarted(() => this.onPageBegin())
|
|
780
|
+
.onLoadFinished(() => this.onLoadFinished())
|
|
781
|
+
.onPageEnd(() => {this.onPageEndExecuteRunInjectedJavaScript()})
|
|
782
|
+
.onErrorReceive((event: OnErrorReceiveEvent) => this.webViewBaseOperate?.emitLoadingError(event))
|
|
783
|
+
.onHttpErrorReceive((event: OnHttpErrorReceiveEvent) => this.webViewBaseOperate?.emitHttpError(event))
|
|
784
|
+
.onControllerAttached(() => this.controllerAttachedInit())
|
|
785
|
+
.onAlert((event: AlertEvent) => this.onJavascriptAlert(event))
|
|
786
|
+
.onConfirm((event: AlertEvent) => this.onJavascriptConfirm(event))
|
|
787
|
+
.onDownloadStart((event: OnDownloadStartEvent) => this.webViewBaseOperate?.onDownloadStart(event))
|
|
788
|
+
.geolocationAccess(this.descriptorWrapper.rawProps.geolocationEnabled)
|
|
789
|
+
.onGeolocationShow((event) => {
|
|
790
|
+
if (event && (this.descriptorWrapper.rawProps.geolocationEnabled != undefined)) {
|
|
791
|
+
event.geolocation.invoke(event.origin, this.descriptorWrapper.rawProps.geolocationEnabled, true);
|
|
792
|
+
}
|
|
793
|
+
})
|
|
794
|
+
.mediaPlayGestureAccess(this.descriptorWrapper.rawProps.mediaPlaybackRequiresUserAction)
|
|
795
|
+
.onRenderExited((event: OnRenderExitedEvent) => this.webViewBaseOperate?.onRenderExited(event))
|
|
796
|
+
.onLoadIntercept((event: OnLoadInterceptEvent) => this.onLoadIntercept(event))
|
|
797
|
+
.onTitleReceive((event: OnTitleReceiveEvent) => this.webViewBaseOperate?.onTitleReceive(event))
|
|
798
|
+
.onFullScreenEnter(async () => {
|
|
799
|
+
Logger.debug(TAG, '[WebViewFullScreen] onFullScreenEnter called');
|
|
800
|
+
if (this.allowsFullscreenVideo) {
|
|
801
|
+
await this.handleFullScreenEnter();
|
|
802
|
+
} else {
|
|
803
|
+
Logger.debug(TAG, '[WebViewFullScreen] Fullscreen video disabled by allowsFullscreenVideo');
|
|
804
|
+
}
|
|
805
|
+
})
|
|
806
|
+
.onFullScreenExit(async () => {
|
|
807
|
+
Logger.debug(TAG, '[WebViewFullScreen] onFullScreenExit called');
|
|
808
|
+
await this.handleFullScreenExit();
|
|
809
|
+
})
|
|
810
|
+
.editMenuOptions({
|
|
811
|
+
onCreateMenu: this.onCreateMenu.bind(this),
|
|
812
|
+
onMenuItemClick: this.onMenuItemClick.bind(this),
|
|
813
|
+
})
|
|
814
|
+
} else {
|
|
815
|
+
Web({ src: "", controller: this.controller, renderMode: this.renderMode })
|
|
816
|
+
.mixedMode(this.mode)
|
|
817
|
+
.onPermissionRequest(async (event: OnPermissionRequestEvent) => {
|
|
818
|
+
if (event && (this.getPermissionDialogMessage(event) != "TYPE_SENSOR")) {
|
|
819
|
+
const resources: string[] = event.request.getAccessibleResource();
|
|
820
|
+
if (resources.indexOf('TYPE_AUDIO_CAPTURE') >= 0 || resources.indexOf('TYPE_VIDEO_CAPTURE') >= 0 ) {
|
|
821
|
+
const originUrl = this.webViewBaseOperate?.verifyURLFormat(event.request.getOrigin(), this.source.html,
|
|
822
|
+
this.source.baseUrl);
|
|
823
|
+
const currentUrl = this.webViewBaseOperate?.verifyURLFormat(this.controller.getUrl(), this.source.html,
|
|
824
|
+
this.source.baseUrl);
|
|
825
|
+
const originDomain: string = OSUrl.URL.parseURL(originUrl).hostname;
|
|
826
|
+
const currentDomain: string = OSUrl.URL.parseURL(currentUrl).hostname;
|
|
827
|
+
let mediaCapturePermissionGrantType: string = WebMediaCapturePermissionGrantType.PROMPT
|
|
828
|
+
if (this.descriptorWrapper.rawProps.mediaCapturePermissionGrantType != undefined) {
|
|
829
|
+
mediaCapturePermissionGrantType = this.descriptorWrapper.rawProps.mediaCapturePermissionGrantType;
|
|
830
|
+
}
|
|
831
|
+
if (mediaCapturePermissionGrantType != WebMediaCapturePermissionGrantType.DENY) {
|
|
832
|
+
await this.handleMediaCapturePermissionGrantType(resources, originDomain)
|
|
833
|
+
}
|
|
834
|
+
switch (mediaCapturePermissionGrantType) {
|
|
835
|
+
case WebMediaCapturePermissionGrantType.GRANT_IF_SAME_HOST_ELSE_PROMPT:
|
|
836
|
+
if (originDomain != currentDomain) {
|
|
837
|
+
this.onPermissionRequestAlert(event)
|
|
838
|
+
} else {
|
|
839
|
+
event.request.grant(resources);
|
|
840
|
+
}
|
|
841
|
+
break;
|
|
842
|
+
case WebMediaCapturePermissionGrantType.GRANT_IF_SAME_HOST_ELSE_DENY:
|
|
843
|
+
if (originDomain != currentDomain) {
|
|
844
|
+
event.request.deny();
|
|
845
|
+
} else {
|
|
846
|
+
event.request.grant(resources);
|
|
847
|
+
}
|
|
848
|
+
break;
|
|
849
|
+
case WebMediaCapturePermissionGrantType.DENY:
|
|
850
|
+
event.request.deny();
|
|
851
|
+
break;
|
|
852
|
+
case WebMediaCapturePermissionGrantType.GRANT:
|
|
853
|
+
event.request.grant(resources);
|
|
854
|
+
break;
|
|
855
|
+
case WebMediaCapturePermissionGrantType.PROMPT:
|
|
856
|
+
this.onPermissionRequestAlert(event)
|
|
857
|
+
break;
|
|
858
|
+
}
|
|
859
|
+
} else {
|
|
860
|
+
this.onPermissionRequestAlert(event)
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
})
|
|
864
|
+
|
|
865
|
+
.width(this.isFullScreen ? "100%" : this.webviewWidth)
|
|
866
|
+
.height(this.isFullScreen ? "100%" : this.webviewHeight)
|
|
867
|
+
.fileAccess(this.allowFileAccess)
|
|
868
|
+
.constraintSize({ minHeight: MINHEIGHT })
|
|
869
|
+
.overScrollMode(this.overScrollMode)
|
|
870
|
+
.javaScriptAccess(this.javaScriptEnable)
|
|
871
|
+
.javaScriptOnDocumentStart(this.injectedJavaScriptBeforeContentLoaded)
|
|
872
|
+
.horizontalScrollBarAccess(this.descriptorWrapper.rawProps.showsHorizontalScrollIndicator)
|
|
873
|
+
.verticalScrollBarAccess(this.descriptorWrapper.rawProps.showsVerticalScrollIndicator)
|
|
874
|
+
.overviewModeAccess(this.descriptorWrapper.rawProps.scalesPageToFit)
|
|
875
|
+
.textZoomRatio(this.descriptorWrapper.rawProps.textZoom)
|
|
876
|
+
.backgroundColor(BaseOperate.getColorMode(this.ctx.uiAbilityContext,
|
|
877
|
+
this.descriptorWrapper.rawProps.forceDarkOn) === WebDarkMode.On ? Color.Black : Color.Transparent)
|
|
878
|
+
.darkMode(BaseOperate.getColorMode(this.ctx.uiAbilityContext, this.descriptorWrapper.rawProps.forceDarkOn))
|
|
879
|
+
.forceDarkAccess(this.forceDark)
|
|
880
|
+
.cacheMode(this.cacheMode)
|
|
881
|
+
.minFontSize(this.minFontSize)
|
|
882
|
+
.domStorageAccess(this.descriptorWrapper.rawProps.domStorageEnabled)
|
|
883
|
+
.zoomAccess(this.descriptorWrapper.rawProps.scalesPageToFit)
|
|
884
|
+
.overScrollMode(this.overScrollMode)
|
|
885
|
+
.onProgressChange((event: OnProgressChangeEvent) => this.onProgressChange(event))
|
|
886
|
+
.onScroll((event: OnScrollEvent) => this.webViewBaseOperate?.emitScroll(event))
|
|
887
|
+
.nestedScroll({
|
|
888
|
+
scrollForward: this.nestedScroll,
|
|
889
|
+
scrollBackward: this.nestedScroll,
|
|
890
|
+
})
|
|
891
|
+
.onPageBegin(() => this.onPageBegin())
|
|
892
|
+
.onPageEnd(() => this.onPageEnd())
|
|
893
|
+
.onErrorReceive((event: OnErrorReceiveEvent) => this.webViewBaseOperate?.emitLoadingError(event))
|
|
894
|
+
.onHttpErrorReceive((event: OnHttpErrorReceiveEvent) => this.webViewBaseOperate?.emitHttpError(event))
|
|
895
|
+
.onControllerAttached(() => this.controllerAttachedInit())
|
|
896
|
+
.onAlert((event: AlertEvent) => this.onJavascriptAlert(event))
|
|
897
|
+
.onConfirm((event: AlertEvent) => this.onJavascriptConfirm(event))
|
|
898
|
+
.onDownloadStart((event: OnDownloadStartEvent) => this.webViewBaseOperate?.onDownloadStart(event))
|
|
899
|
+
.geolocationAccess(this.descriptorWrapper.rawProps.geolocationEnabled)
|
|
900
|
+
.onGeolocationShow((event) => {
|
|
901
|
+
if (event && (this.descriptorWrapper.rawProps.geolocationEnabled != undefined)) {
|
|
902
|
+
event.geolocation.invoke(event.origin, this.descriptorWrapper.rawProps.geolocationEnabled, true);
|
|
903
|
+
}
|
|
904
|
+
})
|
|
905
|
+
.mediaPlayGestureAccess(this.descriptorWrapper.rawProps.mediaPlaybackRequiresUserAction)
|
|
906
|
+
.onRenderExited((event: OnRenderExitedEvent) => this.webViewBaseOperate?.onRenderExited(event))
|
|
907
|
+
.onLoadIntercept((event: OnLoadInterceptEvent) => this.onLoadIntercept(event))
|
|
908
|
+
.onTitleReceive((event: OnTitleReceiveEvent) => this.webViewBaseOperate?.onTitleReceive(event))
|
|
909
|
+
.onFullScreenEnter(async () => {
|
|
910
|
+
Logger.debug(TAG, '[WebViewFullScreen] onFullScreenEnter called');
|
|
911
|
+
if (this.allowsFullscreenVideo) {
|
|
912
|
+
await this.handleFullScreenEnter();
|
|
913
|
+
} else {
|
|
914
|
+
Logger.debug(TAG, '[WebViewFullScreen] Fullscreen video disabled by allowsFullscreenVideo');
|
|
915
|
+
}
|
|
916
|
+
})
|
|
917
|
+
.onFullScreenExit(async () => {
|
|
918
|
+
Logger.debug(TAG, '[WebViewFullScreen] onFullScreenExit called');
|
|
919
|
+
await this.handleFullScreenExit();
|
|
920
|
+
})
|
|
921
|
+
.editMenuOptions({
|
|
922
|
+
onCreateMenu: this.onCreateMenu.bind(this),
|
|
923
|
+
onMenuItemClick: this.onMenuItemClick.bind(this),
|
|
924
|
+
})
|
|
925
|
+
}
|
|
926
|
+
}
|
|
927
|
+
.width(this.isFullScreen ? "100%" : this.webviewWidth)
|
|
928
|
+
.height(this.isFullScreen ? "100%" : this.webviewHeight)
|
|
929
|
+
.position(this.isFullScreen ? undefined : {
|
|
930
|
+
x: this.descriptorWrapper.layoutMetrics.frame.origin.x,
|
|
931
|
+
y: this.descriptorWrapper.layoutMetrics.frame.origin.y
|
|
932
|
+
})
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
private onDescriptorWrapperChange(descriptorWrapper: WebViewDescriptor) {
|
|
936
|
+
this.initVariable()
|
|
937
|
+
this.descriptorWrapper = descriptorWrapper
|
|
938
|
+
if (this.source.html != "" && this.html != this.source.html) {
|
|
939
|
+
if (this.controllerAttached) {
|
|
940
|
+
this.loadHtmlData(this.source.html, this.source.baseUrl)
|
|
941
|
+
Logger.debug(TAG, "[RNOH] html is update")
|
|
942
|
+
this.html = this.source.html
|
|
943
|
+
}
|
|
944
|
+
} else if (this.source.uri && this.source.method && this.source.method.toUpperCase() === 'POST' && this.source.body && (this.source.uri != this.url || this.body != this.source.body)) {
|
|
945
|
+
if (this.controllerAttached) {
|
|
946
|
+
let url = this.source.uri as string;
|
|
947
|
+
this.url = url;
|
|
948
|
+
this.body = this.source.body;
|
|
949
|
+
let postData = buffer.from(this.source.body);
|
|
950
|
+
this.controller.postUrl(url, postData?.buffer);
|
|
951
|
+
}
|
|
952
|
+
} else if (typeof this.url !== typeof this.source.uri
|
|
953
|
+
|| (typeof this.source.uri === "string" && this.url !== this.source.uri)
|
|
954
|
+
|| (typeof this.source.uri === "object" && ( this.url as Resource )?.params !== this.source.uri?.params)) {
|
|
955
|
+
if (this.source.uri != "") {
|
|
956
|
+
Logger.debug(TAG, `[RNOH] newDescriptor props update uri: ` + this.source.uri);
|
|
957
|
+
if (this.controllerAttached) {
|
|
958
|
+
this.controller.loadUrl(this.source.uri, this.headers)
|
|
959
|
+
}
|
|
960
|
+
} else {
|
|
961
|
+
this.loadHtmlData()
|
|
962
|
+
}
|
|
963
|
+
this.url = this.source.uri as string;
|
|
964
|
+
}
|
|
965
|
+
if (this.controllerAttached) {
|
|
966
|
+
this.controller?.setScrollable(this.descriptorWrapper.rawProps.scrollEnabled)
|
|
967
|
+
}
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
private initVariable() {
|
|
971
|
+
this.descriptorWrapper = this.ctx.descriptorRegistry.getDescriptor<WebViewDescriptor>(this.tag)
|
|
972
|
+
this.javaScriptEnable = this.descriptorWrapper.rawProps.javaScriptEnabled;
|
|
973
|
+
this.minFontSize =
|
|
974
|
+
this.descriptorWrapper.rawProps.minimumFontSize ? this.descriptorWrapper.rawProps.minimumFontSize : EIGHT;
|
|
975
|
+
this.cacheMode =
|
|
976
|
+
this.descriptorWrapper.rawProps.cacheEnabled ?
|
|
977
|
+
this.webViewBaseOperate?.transCacheMode(this.descriptorWrapper.rawProps.cacheMode as CACHE_MODE) as number :
|
|
978
|
+
CacheMode.Online;
|
|
979
|
+
this.source = {
|
|
980
|
+
uri: this.descriptorWrapper.rawProps.newSource.uri ?? "",
|
|
981
|
+
method: this.descriptorWrapper.rawProps.newSource.method ?? "",
|
|
982
|
+
body: this.descriptorWrapper.rawProps.newSource.body ?? "",
|
|
983
|
+
html: this.descriptorWrapper.rawProps.newSource.html ?? "",
|
|
984
|
+
baseUrl: this.descriptorWrapper.rawProps.newSource.baseUrl ?? "",
|
|
985
|
+
headers: this.descriptorWrapper.rawProps.newSource.headers ?? []
|
|
986
|
+
}
|
|
987
|
+
if (this.source.headers) {
|
|
988
|
+
this.source.headers.forEach(item => {
|
|
989
|
+
if (item.name && item.value) {
|
|
990
|
+
this.headers.push({ headerKey: item.name, headerValue: item.value })
|
|
991
|
+
}
|
|
992
|
+
})
|
|
993
|
+
}
|
|
994
|
+
// 防抖处理webview尺寸设置
|
|
995
|
+
const newWidth = this.descriptorWrapper.layoutMetrics.frame.size.width
|
|
996
|
+
const newHeight = this.descriptorWrapper.layoutMetrics.frame.size.height
|
|
997
|
+
|
|
998
|
+
if (this.debounceTimer !== -1) {
|
|
999
|
+
clearTimeout(this.debounceTimer)
|
|
1000
|
+
this.debounceTimer = -1
|
|
1001
|
+
}
|
|
1002
|
+
|
|
1003
|
+
if (this.isFirstDebounce) {
|
|
1004
|
+
this.webviewWidth = newWidth
|
|
1005
|
+
this.webviewHeight = newHeight
|
|
1006
|
+
this.isFirstDebounce = false // 标记为非首次
|
|
1007
|
+
} else {
|
|
1008
|
+
this.debounceTimer = setTimeout(() => {
|
|
1009
|
+
this.webviewWidth = newWidth
|
|
1010
|
+
this.webviewHeight = newHeight
|
|
1011
|
+
}, RNCWebView.DEBOUNCE_TIME)
|
|
1012
|
+
}
|
|
1013
|
+
this.scrollEnabled = this.descriptorWrapper.rawProps.scrollEnabled;
|
|
1014
|
+
// 当禁止滚动时,使用父组件滚动
|
|
1015
|
+
this.nestedScroll = this.scrollEnabled ? NestedScrollMode.SELF_FIRST : NestedScrollMode.PARENT_FIRST;
|
|
1016
|
+
if (this.source.uri && this.source.uri.toString().startsWith("asset://")) {
|
|
1017
|
+
this.source.uri = $rawfile(this.source.uri.toString().replace("asset://", this.ctx.rnInstance.getAssetsDest()));
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
if (this.descriptorWrapper.rawProps.overScrollMode === WebViewOverScrollMode.ALWAYS) {
|
|
1021
|
+
this.overScrollMode = OverScrollMode.ALWAYS
|
|
1022
|
+
} else if (this.descriptorWrapper.rawProps.overScrollMode === WebViewOverScrollMode.NEVER) {
|
|
1023
|
+
this.overScrollMode = OverScrollMode.NEVER
|
|
1024
|
+
}
|
|
1025
|
+
|
|
1026
|
+
this.overScrollMode = this.descriptorWrapper.rawProps.bounces ? OverScrollMode.ALWAYS : OverScrollMode.NEVER;
|
|
1027
|
+
|
|
1028
|
+
if (this.descriptorWrapper.rawProps.injectedJavaScriptBeforeContentLoaded) {
|
|
1029
|
+
this.injectedJavaScriptBeforeContentLoaded = [
|
|
1030
|
+
{ script: this.descriptorWrapper.rawProps.injectedJavaScriptBeforeContentLoaded, scriptRules: ["*"] }
|
|
1031
|
+
];
|
|
1032
|
+
}
|
|
1033
|
+
|
|
1034
|
+
const renderModeStr = this.descriptorWrapper.rawProps.renderMode || "SYNC_RENDER"
|
|
1035
|
+
this.renderMode = (renderModeStr === "ASYNC_RENDER") ? RenderMode.ASYNC_RENDER : RenderMode.SYNC_RENDER
|
|
1036
|
+
this.allowsFullscreenVideo = this.descriptorWrapper.rawProps.allowsFullscreenVideo ?? false;
|
|
1037
|
+
|
|
1038
|
+
}
|
|
1039
|
+
|
|
1040
|
+
private registerJavaScriptProxyOnly() {
|
|
1041
|
+
if (this.messagingEnabled == this.descriptorWrapper.rawProps.messagingEnabled && this.hasRegisterJavaScriptProxy) {
|
|
1042
|
+
return;
|
|
1043
|
+
}
|
|
1044
|
+
this.messagingEnabled = this.descriptorWrapper.rawProps.messagingEnabled;
|
|
1045
|
+
if (this.messagingEnabled) {
|
|
1046
|
+
let bridge: RNCWebViewBridge = {
|
|
1047
|
+
postMessage: (data: string) => {
|
|
1048
|
+
Logger.debug(TAG, `[RNOH] bridge postMessage, ${JSON.stringify(data)}`);
|
|
1049
|
+
if (this.controller != null) {
|
|
1050
|
+
let result: WebViewEventParams = this.createWebViewEvent("onMessage")
|
|
1051
|
+
if (result) {
|
|
1052
|
+
result.data = data.toString()
|
|
1053
|
+
result.lockIdentifier = this.webViewBaseOperate?.getLockIdentifier()
|
|
1054
|
+
this.eventEmitter!.emit("message", result as ResultType);
|
|
1055
|
+
}
|
|
1056
|
+
}
|
|
1057
|
+
}
|
|
1058
|
+
};
|
|
1059
|
+
this.controller.registerJavaScriptProxy(bridge, JAVASCRIPT_INTERFACE, ["postMessage"])
|
|
1060
|
+
this.hasRegisterJavaScriptProxy = true
|
|
1061
|
+
Logger.debug(TAG, "[RNOH] JavaScript Proxy registered without reloading page")
|
|
1062
|
+
}
|
|
1063
|
+
}
|
|
1064
|
+
|
|
1065
|
+
private registerPostMessage() {
|
|
1066
|
+
if (this.messagingEnabled == this.descriptorWrapper.rawProps.messagingEnabled) {
|
|
1067
|
+
return;
|
|
1068
|
+
}
|
|
1069
|
+
this.messagingEnabled = this.descriptorWrapper.rawProps.messagingEnabled;
|
|
1070
|
+
if (this.messagingEnabled) {
|
|
1071
|
+
if (this.hasRegisterJavaScriptProxy) {
|
|
1072
|
+
Logger.debug(TAG, "[RNOH] JavaScript Proxy already registered")
|
|
1073
|
+
return
|
|
1074
|
+
}
|
|
1075
|
+
let bridge: RNCWebViewBridge = {
|
|
1076
|
+
postMessage: (data: string) => {
|
|
1077
|
+
Logger.debug(TAG, `[RNOH] bridge postMessage, ${JSON.stringify(data)}`);
|
|
1078
|
+
if (this.controller != null) {
|
|
1079
|
+
let result: WebViewEventParams = this.createWebViewEvent("onMessage")
|
|
1080
|
+
if (result) {
|
|
1081
|
+
result.data = data.toString()
|
|
1082
|
+
result.lockIdentifier = this.webViewBaseOperate?.getLockIdentifier()
|
|
1083
|
+
this.eventEmitter!.emit("message", result as ResultType);
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
1086
|
+
}
|
|
1087
|
+
};
|
|
1088
|
+
this.controller.registerJavaScriptProxy(bridge, JAVASCRIPT_INTERFACE, ["postMessage"])
|
|
1089
|
+
if (this.source.uri && !this.source.html) {
|
|
1090
|
+
this.controller.loadUrl(this.source.uri, this.headers)
|
|
1091
|
+
} else if (this.source.html) {
|
|
1092
|
+
Logger.debug(TAG, "[RNOH] JavaScript Proxy registered, HTML content will use it on next load")
|
|
1093
|
+
} else {
|
|
1094
|
+
this.controller.refresh()
|
|
1095
|
+
}
|
|
1096
|
+
this.hasRegisterJavaScriptProxy = true
|
|
1097
|
+
}
|
|
1098
|
+
}
|
|
904
1099
|
}
|