diff --git a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/types/SslCertificate.ets b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/types/ClientCertChallenge.ets similarity index 34% rename from flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/types/SslCertificate.ets rename to flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/types/ClientCertChallenge.ets index d0a0ad4583500653114c1125a63a3527f4cb717d..78ac6a278ce6f0d48a0b151b20e976d9c35b160f 100644 --- a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/types/SslCertificate.ets +++ b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/types/ClientCertChallenge.ets @@ -12,54 +12,41 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import { Any } from '@ohos/flutter_ohos'; -export default class SslCertificate { - private static ISO_8601_DATE_FORMAT: string = "yyyy-MM-dd HH:mm:ssZ" - private mIssuedTo: DName - private mIssuedBy: DName - private mValidNotBefore: Date | null - private mValidNotAfter: Date | null +import URLAuthenticationChallenge from './URLAuthenticationChallenge'; +import URLProtectionSpace from './URLProtectionSpace'; - constructor(issuedTo: string, issuedBy: string, validNotBefore: Date, validNotAfter: Date) { - this.mIssuedTo = new DName(issuedTo); - this.mIssuedBy = new DName(issuedBy); - this.mValidNotBefore = this.cloneDate(validNotBefore); - this.mValidNotAfter = this.cloneDate(validNotAfter); - } +export default class ClientCertChallenge extends URLAuthenticationChallenge { + private principals: Array | null; + private keyTypes: Array | null; - private cloneDate(date: Date): Date | null { - if (date == null) { - return null; - } - return date; + constructor(protectionSpace: URLProtectionSpace, principals: Array | null, keyTypes: Array | null) { + super(protectionSpace); + this.principals = principals; + this.keyTypes = keyTypes; } -} - -export class DName { - private mDName: string | null = null - private mCName: string | null = null - private mOName: string | null = null - private mUName: string | null = null - constructor(dName: string) { - if(dName != null) { - this.mDName = dName; - } + public async toMap() { + let challengeMap: Map = await super.toMap(); + challengeMap.set("principals", this.principals ? this.principals : null); + challengeMap.set("keyTypes", this.keyTypes != null ? this.keyTypes : null); + return challengeMap; } - public getDName(): string { - return this.mDName != null ? this.mDName : ""; + public getPrincipals(): Array | null { + return this.principals; } - public getCName(): string { - return this.mCName != null ? this.mCName : ""; + public setPrincipals(principals: Array | null): void { + this.principals = principals; } - public getOName(): string { - return this.mOName != null ? this.mOName : ""; + public getKeyTypes(): Array | null { + return this.keyTypes; } - public getUName(): string { - return this.mUName != null ? this.mUName : ""; + public setKeyTypes(keyTypes: Array | null): void { + this.keyTypes = keyTypes; } } \ No newline at end of file diff --git a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/types/ClientCertResponse.ets b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/types/ClientCertResponse.ets new file mode 100644 index 0000000000000000000000000000000000000000..07ebc9f14b38650a179e300ebba1aa92913b9c9f --- /dev/null +++ b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/types/ClientCertResponse.ets @@ -0,0 +1,73 @@ +/* +* Copyright (c) 2024 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +import { Any } from '@ohos/flutter_ohos'; + +export default class ClientCertResponse { + private certificatePath: string; + private certificatePassword: string; + private keyStoreType: string; + private action: number; + + constructor(certificatePath: string, certificatePassword: string, keyStoreType: string, action: number) { + this.certificatePath = certificatePath; + this.certificatePassword = certificatePassword; + this.keyStoreType = keyStoreType; + this.action = action; + } + + public static fromMap(map: Map): ClientCertResponse | null { + if (map == null) { + return null; + } + let certificatePath: string = map.get("certificatePath"); + let certificatePassword: string = map.get("certificatePassword"); + let keyStoreType: string = map.get("keyStoreType"); + let action: number = map.get("action"); + + return new ClientCertResponse(certificatePath, certificatePassword, keyStoreType, action); + } + + getCertificatePath(): string { + return this.certificatePath; + } + + public setCertificatePath(certificatePath: string) { + this.certificatePath = certificatePath; + } + + public getCertificatePassword(): string { + return this.certificatePassword; + } + + public setCertificatePassword(certificatePassword: string) { + this.certificatePassword = certificatePassword; + } + + public getKeyStoreType(): string { + return this.keyStoreType; + } + + public setKeyStoreType(keyStoreType: string) { + this.keyStoreType = keyStoreType; + } + + public getAction(): number { + return this.action; + } + + public setAction(action: number) { + this.action = action; + } +} \ No newline at end of file diff --git a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/types/HitTestResult.ets b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/types/HitTestResult.ets index 0782e415cfe06fa3d0ccf1cf476f72d2578529ee..d18645e2b1f43a79e0faec43d74f1dd283c3a565 100644 --- a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/types/HitTestResult.ets +++ b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/types/HitTestResult.ets @@ -29,7 +29,6 @@ export default class HitTestResult { if (hitTestResult == null) { return null; } - return new HitTestResult(hitTestResult.type, hitTestResult.extra); } diff --git a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/types/HttpAuthenticationChallenge.ets b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/types/HttpAuthenticationChallenge.ets index a3e8285bdd15d8caf447b01fd78fbbc272bb2809..00a4189a8b0bba8f43c318f86a7dc371db0df514 100644 --- a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/types/HttpAuthenticationChallenge.ets +++ b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/types/HttpAuthenticationChallenge.ets @@ -28,8 +28,8 @@ export default class HttpAuthenticationChallenge extends URLAuthenticationChalle this.proposedCredential = proposedCredential } - public toMap(): Map { - let challengeMap: Map = super.toMap(); + public async toMap() { + let challengeMap: Map = await super.toMap(); challengeMap.set("previousFailureCount", this.previousFailureCount); challengeMap.set("proposedCredential", (this.proposedCredential != null) ? this.proposedCredential.toMap() : null); challengeMap.set("failureResponse", null); diff --git a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/types/SslError.ets b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/types/ServerTrustAuthResponse.ets similarity index 42% rename from flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/types/SslError.ets rename to flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/types/ServerTrustAuthResponse.ets index 4361906ec81b3d421d66fe456907e23cb7f9d835..08de5c5f11191f0d64191a4a397d3ed052b9ec5f 100644 --- a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/types/SslError.ets +++ b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/types/ServerTrustAuthResponse.ets @@ -13,40 +13,25 @@ * limitations under the License. */ -import SslCertificate from './SslCertificate' -export default class SslError { - public static SSL_NOTYETVALID: number = 0 - public static SSL_EXPIRED: number = 1 - public static SSL_IDMISMATCH: number = 2 - public static SSL_UNTRUSTED: number = 3 - public static SSL_DATE_INVALID: number = 4 - public static SSL_INVALID: number = 5 +import { Any } from '@ohos/flutter_ohos' - public static SSL_MAX_ERROR: number = 6 +export default class ServerTrustAuthResponse { + private action: number - mErrors: number - - mCertificate: SslCertificate - - mUrl: string + constructor(action: number) { + this.action = action + } - constructor(error: number, certificate: SslCertificate, url: string) { - // if(certificate == null) return - // if(url == null) return - this.addError(error) - this.mErrors = error - this.mCertificate = certificate; - this.mUrl = url; + getAction(): number { + return this.action; } - public addError(error: number): boolean { - let rval: boolean = (0 <= error && error < SslError.SSL_MAX_ERROR); - if (rval) { - this.mErrors |= (0x1 << error); + public static fromMap(map: Map): ServerTrustAuthResponse | null { + if (map == null) { + return null; } - - return rval; + let action: number = map.get("action") as number; + return new ServerTrustAuthResponse(action); } - } \ No newline at end of file diff --git a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/types/ServerTrustChallenge.ets b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/types/ServerTrustChallenge.ets new file mode 100644 index 0000000000000000000000000000000000000000..23f5a6de393d2046f8bcaebb4648c7d2ca328e1d --- /dev/null +++ b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/types/ServerTrustChallenge.ets @@ -0,0 +1,24 @@ +/* +* Copyright (c) 2024 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + + +import URLAuthenticationChallenge from './URLAuthenticationChallenge' +import URLProtectionSpace from './URLProtectionSpace' + +export default class ServerTrustChallenge extends URLAuthenticationChallenge { + constructor(protectionSpace: URLProtectionSpace) { + super(protectionSpace); + } +} \ No newline at end of file diff --git a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/types/SslCertificateExt.ets b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/types/SslCertificateExt.ets index da4513b68d0c820228e936bc69e4c4c1abe7b351..8fc8d5ebfb3967b059c7d7bc400134dff539e965 100644 --- a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/types/SslCertificateExt.ets +++ b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/types/SslCertificateExt.ets @@ -17,37 +17,116 @@ import cert from '@ohos.security.cert'; import { Any } from '@ohos/flutter_ohos'; export default class SslCertificateExt { - constructor() {} + constructor() { + } - public static toMap(X509Cert: Array | null): Map | null{ - if(X509Cert == null) { + public static async toMap(x509Cert: cert.X509Cert | null) { + if (x509Cert == null) { return null } - let sslCertificateMap: Map = new Map(); + let issuerName = x509Cert.getIssuerName(); + let issuedByName = extractFields(Uint8ArrayToString(issuerName.data)) + let issuedBy: Map | null = null; + if (issuedByName != null) { + issuedBy = new Map(); + issuedBy.set("CName", issuedByName.cName); + issuedBy.set("DName", issuedByName.dName); + issuedBy.set("OName", issuedByName.oName); + issuedBy.set("UName", issuedByName.uName); + } - for (let i = 0; i < X509Cert.length; i++) { - let x509CertificateData = X509Cert[i].getEncoded() + let subjectName = x509Cert.getSubjectName(); + let issuedToName = extractFields(Uint8ArrayToString(subjectName.data)) + let issuedTo: Map | null = null; + if (issuedToName != null) { + issuedTo = new Map(); + issuedTo.set("CName", issuedToName.cName); + issuedTo.set("DName", issuedToName.dName); + issuedTo.set("OName", issuedToName.oName); + issuedTo.set("UName", issuedToName.uName); + } - let validNotAfterDate: string = X509Cert[i].getNotAfterTime() - let validNotBeforeDate: string = X509Cert[i].getNotBeforeTime() + let sslCertificateMap: Map = new Map(); - sslCertificateMap.set("issuedBy", Uint8ArrayToString(X509Cert[i].getIssuerName().data)); - sslCertificateMap.set("issuedTo", Uint8ArrayToString(X509Cert[i].getSubjectName().data)); - sslCertificateMap.set("validNotAfterDate", validNotAfterDate); - sslCertificateMap.set("validNotBeforeDate", validNotBeforeDate); - sslCertificateMap.set("x509Certificate", x509CertificateData); - } + let x509CertificateData = await x509Cert.getEncoded() + let validNotAfterDate: string = x509Cert.getNotAfterTime() + let validNotBeforeDate: string = x509Cert.getNotBeforeTime() + sslCertificateMap.set("issuedBy", issuedBy); + sslCertificateMap.set("issuedTo", issuedTo); + sslCertificateMap.set("validNotAfterDate", asn1TimeToTimestamp(validNotAfterDate)); + sslCertificateMap.set("validNotBeforeDate", asn1TimeToTimestamp(validNotBeforeDate)); + sslCertificateMap.set("x509Certificate", x509CertificateData.data); return sslCertificateMap; } } -function Uint8ArrayToString(dataArray:Uint8Array) { +interface DName { + cName: string + dName: string + oName: string + uName: string +} + +function extractFields(subjectName: string): DName { + const subject = subjectName.split(', '); + const fields: ESObject = {}; + subject.forEach(attr => { + const values = attr.split('='); + fields[values[0]] = values[1].trim(); + }); + return { + cName: fields['CN'] || '', + dName: subjectName || '', + oName: fields['O'] || '', + uName: fields['OU'] || '' + }; +} + +function Uint8ArrayToString(dataArray: Uint8Array): string { let dataString = '' for (let i = 0; i < dataArray.length; i++) { dataString += String.fromCharCode(dataArray[i]) } return dataString +} + +/** + * 将ASN.1时间字符串转换为时间戳 + * @param {string} asn1Time - ASN.1时间字符串 + * @returns {number} 时间戳(毫秒) + */ +function asn1TimeToTimestamp(asn1Time: string): number { + let year: number = 0; + let month: number = 0; + let day: number = 0; + let hours: number = 0; + let minutes: number = 0; + let seconds: number = 0; + + if (asn1Time.length === 13) { + // UTC Time格式 (YYMMDDHHMMSSZ) + year = parseInt(asn1Time.slice(0, 2), 10); + year += year < 50 ? 2000 : 1900; + month = parseInt(asn1Time.slice(2, 4), 10) - 1; + day = parseInt(asn1Time.slice(4, 6), 10); + hours = parseInt(asn1Time.slice(6, 8), 10); + minutes = parseInt(asn1Time.slice(8, 10), 10); + seconds = parseInt(asn1Time.slice(10, 12), 10); + } else if (asn1Time.length === 15) { + // Generalized Time格式 (YYYYMMDDHHMMSSZ) + year = parseInt(asn1Time.slice(0, 4), 10); + month = parseInt(asn1Time.slice(4, 6), 10) - 1; + day = parseInt(asn1Time.slice(6, 8), 10); + hours = parseInt(asn1Time.slice(8, 10), 10); + minutes = parseInt(asn1Time.slice(10, 12), 10); + seconds = parseInt(asn1Time.slice(12, 14), 10); + } else { + throw new Error('Unsupported ASN.1 time format'); + } + // 创建Date对象并返回时间戳 + const date = new Date(Date.UTC(year, month, day, hours, minutes, seconds)); + return date.getTime(); } \ No newline at end of file diff --git a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/types/SslErrorExt.ets b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/types/SslErrorExt.ets new file mode 100644 index 0000000000000000000000000000000000000000..309f4eeec4871a58f4bd78c89b57066b4d099a85 --- /dev/null +++ b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/types/SslErrorExt.ets @@ -0,0 +1,66 @@ +/* +* Copyright (c) 2024 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + + +import { Any } from '@ohos/flutter_ohos'; + +export default class SslErrorExt { + constructor() { + } + + public static toMap(sslError: SslError | null): Map | null { + if (sslError == null) { + return null + } + + let message: string | null = null; + + switch (sslError) { + case SslError.DateInvalid: + message = "The date of the certificate is invalid"; + break; + case SslError.HostMismatch: + message = "Hostname mismatch"; + break; + case SslError.Invalid: + message = "A generic error occurred"; + break; + case SslError.Untrusted: + message = "The certificate authority is not trusted"; + break; + default: + message = null; + break; + } + + let urlProtectionSpaceMap : Map = new Map(); + urlProtectionSpaceMap.set("code", covertSslErrorCode(sslError)); + urlProtectionSpaceMap.set("message", message); + return urlProtectionSpaceMap; + } +} + +function covertSslErrorCode(sslError: SslError) { + if (sslError == SslError.DateInvalid) { + return 4; + } else if (sslError == SslError.HostMismatch) { + return 2; + } else if (sslError == SslError.Invalid) { + return 5; + } else if (sslError == SslError.Untrusted) { + return 3; + } + return 0; +} \ No newline at end of file diff --git a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/types/URLAuthenticationChallenge.ets b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/types/URLAuthenticationChallenge.ets index bce63e306ab2e769c783b609166f5b7558f4db85..9d57534592ac273de8d02ad7db4af920f24bdcc2 100644 --- a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/types/URLAuthenticationChallenge.ets +++ b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/types/URLAuthenticationChallenge.ets @@ -23,9 +23,9 @@ export default class URLAuthenticationChallenge { this.protectionSpace = protectionSpace } - public toMap(): Map { + public async toMap() { let challengeMap: Map = new Map(); - challengeMap.set("protectionSpace", this.protectionSpace.toMap()); + challengeMap.set("protectionSpace", await this.protectionSpace.toMap()); return challengeMap; } diff --git a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/types/URLProtectionSpace.ets b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/types/URLProtectionSpace.ets index c5a66d9338bb615ac3b1270b0629e76a81f03533..8c0fd23471e31c5a184c03d7d7eecc0e5e1e5284 100644 --- a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/types/URLProtectionSpace.ets +++ b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/types/URLProtectionSpace.ets @@ -14,8 +14,8 @@ */ import { Any } from '@ohos/flutter_ohos' -import SslCertificate from './SslCertificate' -import SslError from './SslError' +import SslCertificateExt from './SslCertificateExt' +import SslErrorExt from './SslErrorExt' import { cert } from '@kit.DeviceCertificateKit' export default class URLProtectionSpace { @@ -44,16 +44,15 @@ export default class URLProtectionSpace { } } - public toMap(): Map { - // TODO + public async toMap() { let urlProtectionSpaceMap: Map = new Map(); urlProtectionSpaceMap.set("host", this.host); urlProtectionSpaceMap.set("protocol", this.protocol); urlProtectionSpaceMap.set("realm", this.realm); urlProtectionSpaceMap.set("port", this.port); - // urlProtectionSpaceMap.set("sslCertificate", SslCertificateExt.toMap(this.sslCertificate)); + urlProtectionSpaceMap.set("sslCertificate", await SslCertificateExt.toMap(this.sslCertificate)); urlProtectionSpaceMap.set("sslCertificate", null); - // urlProtectionSpaceMap.set("sslError", SslErrorExt.toMap(this.sslError)); + urlProtectionSpaceMap.set("sslError", SslErrorExt.toMap(this.sslError)); urlProtectionSpaceMap.set("sslError", null); urlProtectionSpaceMap.set("authenticationMethod", null); urlProtectionSpaceMap.set("distinguishedNames", null); diff --git a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/webview/InAppWebViewInterface.ets b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/webview/InAppWebViewInterface.ets index 36f3bce9bfce230377908bf3c051273762ac3eff..1fad79c76b5a83fe9783b0bb266819f87f8de97d 100644 --- a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/webview/InAppWebViewInterface.ets +++ b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/webview/InAppWebViewInterface.ets @@ -141,7 +141,7 @@ export default interface InAppWebViewInterface { clearFocus(): void - getCertificate(): Promise> + getCertificate(): Promise clearHistory(): void diff --git a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/webview/InAppWebViewManager.ets b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/webview/InAppWebViewManager.ets index e9cd1863d2c90393a99a33d26679fd7414462137..4a220839ab4bb5b753757ee828c8de1b49423ded 100644 --- a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/webview/InAppWebViewManager.ets +++ b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/webview/InAppWebViewManager.ets @@ -35,8 +35,7 @@ export class InAppWebViewManager extends ChannelDelegateImpl { public controller: web_webview.WebviewController = new web_webview.WebviewController(); - /// 机制不同,缺少类似于android.os.message方法 - // public windowWebViewMessages: Map = new Map() + public windowWebViewMessages: Map = new Map() public windowAutoincrementId: number = 0 @@ -65,27 +64,27 @@ export class InAppWebViewManager extends ChannelDelegateImpl { } break; case "getSafeBrowsingPrivacyPolicyUrl": - /// 返回指向安全浏览报告的隐私策略的URL。 + /// 返回指向安全浏览报告的隐私策略的URL。 result.success(null); break; case "setSafeBrowsingAllowlist": - /// 配置一组免于安全浏览检查的主机(域名/IP地址) - /// ohos非法和欺诈网站是强制启用的 - /// 目前还未找到实现方法 + /// 配置一组免于安全浏览检查的主机(域名/IP地址) + /// ohos非法和欺诈网站是强制启用的 + /// 目前还未找到实现方法 result.success(false); break; case "getCurrentWebViewPackage": - // { - // Context context = null; - // if (plugin != null) { - // context = plugin.activity; - // if (context == null) { - // context = plugin.applicationContext; - // } - // } - // PackageInfo packageInfo = context != null ? WebViewCompat.getCurrentWebViewPackage(context) : null; - // result.success(packageInfo != null ? convertWebViewPackageToMap(packageInfo) : null); - // } + // { + // Context context = null; + // if (plugin != null) { + // context = plugin.activity; + // if (context == null) { + // context = plugin.applicationContext; + // } + // } + // PackageInfo packageInfo = context != null ? WebViewCompat.getCurrentWebViewPackage(context) : null; + // result.success(packageInfo != null ? convertWebViewPackageToMap(packageInfo) : null); + // } break; case "setWebContentsDebuggingEnabled": { @@ -95,11 +94,11 @@ export class InAppWebViewManager extends ChannelDelegateImpl { result.success(true); break; case "getVariationsHeader": - /// 获取编码后用作X-Client-Data HTTP标头的WebView变体,未找到实现 + /// 获取编码后用作X-Client-Data HTTP标头的WebView变体,未找到实现 result.success(null); break; case "isMultiProcessEnabled": - /// 监测WebView是否在多进程模式下运行,未找到对应实现 + /// 监测WebView是否在多进程模式下运行,未找到对应实现 result.success(false); break; case "disableWebView": @@ -114,19 +113,19 @@ export class InAppWebViewManager extends ChannelDelegateImpl { result.success(true); break; case "clearAllCache": - // { - // Context context = null; - // if (plugin != null) { - // context = plugin.activity; - // if (context == null) { - // context = plugin.applicationContext; - // } - // if (context != null) { - // boolean includeDiskFiles = (boolean) call.argument("includeDiskFiles"); - // clearAllCache(context, includeDiskFiles); - // } - // } - // } + // { + // Context context = null; + // if (plugin != null) { + // context = plugin.activity; + // if (context == null) { + // context = plugin.applicationContext; + // } + // if (context != null) { + // boolean includeDiskFiles = (boolean) call.argument("includeDiskFiles"); + // clearAllCache(context, includeDiskFiles); + // } + // } + // } result.success(true); break; default: @@ -184,7 +183,7 @@ export class InAppWebViewManager extends ChannelDelegateImpl { // } // } this.keepAliveWebViews.clear(); - // this.windowWebViewMessages.clear(); + this.windowWebViewMessages.clear(); this.plugin = null; } } \ No newline at end of file diff --git a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/webview/WebViewChannelDelegate.ets b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/webview/WebViewChannelDelegate.ets index 46a666999edcb17e818efc2bb50488e59215d1c5..87967a1591e8f5e2ae52be2b39115e7bc7fe56b7 100644 --- a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/webview/WebViewChannelDelegate.ets +++ b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/webview/WebViewChannelDelegate.ets @@ -50,6 +50,10 @@ import CustomSchemeResponse from '../types/CustomSchemeResponse'; import { NavigationActionPolicy } from '../types/NavigationActionPolicy'; import NavigationAction from '../types/NavigationAction'; import SslCertificateExt from '../types/SslCertificateExt'; +import ServerTrustAuthResponse from '../types/ServerTrustAuthResponse'; +import ServerTrustChallenge from '../types/ServerTrustChallenge'; +import ClientCertResponse from '../types/ClientCertResponse'; +import ClientCertChallenge from '../types/ClientCertChallenge'; const LOG_TAG = "WebViewChannelDelegate"; @@ -492,7 +496,7 @@ export default class WebViewChannelDelegate extends ChannelDelegateImpl { break; case WebViewChannelDelegateMethods.getCertificate: if (this.webView != null) { - result.success(SslCertificateExt.toMap(await this.webView.getCertificate())); + result.success(await SslCertificateExt.toMap(await this.webView.getCertificate())); } else { result.success(null); } @@ -919,6 +923,15 @@ export default class WebViewChannelDelegate extends ChannelDelegateImpl { channel.invokeMethod("onUpdateVisitedHistory", obj); } + public onRequestFocus() { + let channel: MethodChannel = this.getChannel(); + if (channel == null) { + return; + } + let obj: Map = new Map(); + channel.invokeMethod("onRequestFocus", obj); + } + public onReceivedError(request: WebResourceRequestExt, error: WebResourceErrorExt): void { let channel: MethodChannel = this.getChannel(); if (channel == null) return; @@ -937,13 +950,32 @@ export default class WebViewChannelDelegate extends ChannelDelegateImpl { channel.invokeMethod("onReceivedHttpError", obj); } - public onReceivedHttpAuthRequest(challenge: HttpAuthenticationChallenge, callback: ReceivedHttpAuthRequestCallback) { + public async onReceivedHttpAuthRequest(challenge: HttpAuthenticationChallenge, callback: ReceivedHttpAuthRequestCallback) { + let channel: MethodChannel = this.getChannel(); + if (channel == null) { + callback.defaultBehaviour(null); + return; + } + channel.invokeMethod("onReceivedHttpAuthRequest", await challenge.toMap(), callback); + } + + public async onReceivedServerTrustAuthRequest(challenge: ServerTrustChallenge, callback: ReceivedServerTrustAuthRequestCallback) { + let channel: MethodChannel = this.getChannel(); + if (channel == null) { + callback.defaultBehaviour(null); + return; + } + channel.invokeMethod("onReceivedServerTrustAuthRequest", await challenge.toMap(), callback); + } + + public async onReceivedClientCertRequest(challenge: ClientCertChallenge, + callback: ReceivedClientCertRequestCallback) { let channel: MethodChannel = this.getChannel(); if (channel == null) { callback.defaultBehaviour(null); return; } - channel.invokeMethod("onReceivedHttpAuthRequest", challenge.toMap(), callback); + channel.invokeMethod("onReceivedClientCertRequest", await challenge.toMap(), callback); } async shouldInterceptRequest(request: WebResourceRequestExt) { @@ -1018,6 +1050,22 @@ export default class WebViewChannelDelegate extends ChannelDelegateImpl { obj.set("rendererPriorityAtExit", rendererPriorityAtExit); channel.invokeMethod("onRenderProcessGone", obj); } + + onPageCommitVisible(url: string) { + let channel = this.getChannel(); + if (channel == null) return; + let obj: Map = new Map(); + obj.set("url", url); + channel.invokeMethod("onPageCommitVisible", obj); + } + + onFormResubmission(url: string, callback: FormResubmissionCallback) { + let channel = this.getChannel(); + if (channel == null) return; + let obj: Map = new Map(); + obj.set("url", url); + channel.invokeMethod("onFormResubmission", obj, callback); + } } export class JsAlertCallback extends BaseCallbackResultImpl { @@ -1111,4 +1159,22 @@ export class PrintRequestCallback extends BaseCallbackResultImpl { public decodeResult(obj: Any): boolean { return obj; } +} + +export class ReceivedServerTrustAuthRequestCallback extends BaseCallbackResultImpl { + public decodeResult(obj: Any): ServerTrustAuthResponse | null { + return ServerTrustAuthResponse.fromMap(obj); + } +} + +export class ReceivedClientCertRequestCallback extends BaseCallbackResultImpl { + public decodeResult(obj: Any): ClientCertResponse | null { + return ClientCertResponse.fromMap(obj); + } +} + +export class FormResubmissionCallback extends BaseCallbackResultImpl { + decodeResult(obj: Any): number | null { + return typeof obj == 'number' ? obj as number : null; + } } \ No newline at end of file diff --git a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/webview/in_app_webview/FlutterWebView.ets b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/webview/in_app_webview/FlutterWebView.ets index 23334793862163e62d2f32ed13d2fb90b1535e7c..c745bd5b0039a59b87cbc76f3fd96460b1e18c47 100644 --- a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/webview/in_app_webview/FlutterWebView.ets +++ b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/webview/in_app_webview/FlutterWebView.ets @@ -61,7 +61,7 @@ export class FlutterWebView extends PlatformWebView { }) } - this.webView = new InAppWebView(context, plugin, id, windowId, customSettings, userScripts) + this.webView = new InAppWebView(context, plugin, id, windowId, customSettings, userScripts, contextMenu) displayListenerProxy.onPostWebViewInitialization(); //displayListenerProxy.onPostWebViewInitialization(displayManager); // set MATCH_PARENT layout params to the WebView, otherwise it won't take all the available space! @@ -102,23 +102,14 @@ export class FlutterWebView extends PlatformWebView { let initialData: Map = params.get("initialData"); if (windowId != null && windowId != undefined) { if (this.webView.plugin != null && this.webView.plugin.inAppWebViewManager != null) { - //TODO - // let resultMsg: Message = this.webView.plugin.inAppWebViewManager.windowWebViewMessages.get(windowId); - // if (resultMsg != null) { - // ((WebView.WebViewTransport) resultMsg.obj).setWebView(webView); - // resultMsg.sendToTarget(); - // - // if (WebViewFeature.isFeatureSupported(WebViewFeature.DOCUMENT_START_SCRIPT)) { - // webView.post(new Runnable() { - // @Override - // public void run() { - // if (webView != null) { - // webView.prepareAndAddUserScripts(); - // } - // } - // }); - // } - // } + let resultMsg = this.webView.plugin.inAppWebViewManager.windowWebViewMessages.get(windowId); + if (resultMsg) { + resultMsg.setWebController(this.getController()) + + if (this.webView != null) { + this.webView.prepareAndAddUserScripts(); + } + } } } else { if (initialFile != null) { diff --git a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/webview/in_app_webview/InAppWebView.ets b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/webview/in_app_webview/InAppWebView.ets index ea5de5fe9c3d2b4e8acca3327efe460b404a21c8..070cc431a4572fbb7752700862fe457fa5c3e9ab 100644 --- a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/webview/in_app_webview/InAppWebView.ets +++ b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/webview/in_app_webview/InAppWebView.ets @@ -239,7 +239,7 @@ export default class InAppWebView implements InAppWebViewInterface { web_webview.WebCookieManager.putAcceptThirdPartyCookieEnabled(this.customSettings.thirdPartyCookiesEnabled); } - private prepareAndAddUserScripts(): void { + prepareAndAddUserScripts(): void { this.userContentController.addPluginScript(PromisePolyfillJS.PROMISE_POLYFILL_JS_PLUGIN_SCRIPT); this.userContentController.addPluginScript(JavaScriptBridgeJS.JAVASCRIPT_BRIDGE_JS_PLUGIN_SCRIPT); this.userContentController.addPluginScript(ConsoleLogJS.CONSOLE_LOG_JS_PLUGIN_SCRIPT); @@ -865,8 +865,13 @@ export default class InAppWebView implements InAppWebViewInterface { this.controller.onInactive } - async getCertificate(): Promise> { - return this.controller.getCertificate() + async getCertificate() { + let certificates = await this.controller.getCertificate() + if (certificates && certificates.length > 0) { + return certificates[0] + } else { + return null + } } clearHistory(): void { diff --git a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/webview/in_app_webview/InAppWebViewChromeClient.ets b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/webview/in_app_webview/InAppWebViewChromeClient.ets index 9059ba429cf44863c01e05e3c817d8eafecdf9cd..907faaf17b50833bfd59eedc0c5babd381380044 100644 --- a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/webview/in_app_webview/InAppWebViewChromeClient.ets +++ b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/webview/in_app_webview/InAppWebViewChromeClient.ets @@ -41,7 +41,11 @@ import { JsConfirmCallback, JsPromptCallback, PermissionRequestCallback, - ReceivedHttpAuthRequestCallback + ReceivedHttpAuthRequestCallback, + ReceivedServerTrustAuthRequestCallback, + ReceivedClientCertRequestCallback, + CreateWindowCallback, + FormResubmissionCallback } from '../WebViewChannelDelegate'; import JsAlertResponse from '../../types/JsAlertResponse'; import JsConfirmResponse from '../../types/JsConfirmResponse'; @@ -58,8 +62,14 @@ import GeolocationPermissionShowPromptResponse from '../../types/GeolocationPerm import CredentialDatabase from '../../credential_database/CredentialDatabase'; import HttpAuthenticationChallenge from '../../types/HttpAuthenticationChallenge'; import URLProtectionSpace from '../../types/URLProtectionSpace'; +import ServerTrustAuthResponse from '../../types/ServerTrustAuthResponse'; +import ServerTrustChallenge from '../../types/ServerTrustChallenge'; +import ClientCertChallenge from '../../types/ClientCertChallenge'; +import ClientCertResponse from '../../types/ClientCertResponse'; +import CreateWindowAction from '../../types/CreateWindowAction'; import { cert } from '@kit.DeviceCertificateKit' import { List } from '@kit.ArkTS'; +import { common } from '@kit.AbilityKit'; const TAG = "InAppWebViewChromeClient"; @@ -71,6 +81,8 @@ export default class InAppWebViewChromeClient { private inAppWebView: InAppWebView; private inAppBrowserDelegate: InAppBrowserDelegate | null = null; private fullScreenExitHandler: FullScreenExitHandler | null = null; + private isOriginalLayoutFullScreen = false; + private isOriginalFullScreen = false; constructor(plugin: InAppWebViewFlutterPlugin, inAppWebView: InAppWebView) { this.plugin = plugin; @@ -106,8 +118,6 @@ export default class InAppWebViewChromeClient { } onPrompt = (event: Any, uiObject: Any) => { Log.d(TAG, "onPrompt=" + JSON.stringify(event)) - // TODO - // 等API12适配的时候放开 if (this.inAppWebView != null && this.inAppWebView.channelDelegate != null) { this.inAppWebView.channelDelegate.onJsPrompt(event.url, event.message, event.value, null, new InnerJsPromptCallback(event.result, event.message, event.value, uiObject)); @@ -456,12 +466,12 @@ export default class InAppWebViewChromeClient { return true; } onSslErrorEventReceive = (event: Any) => { - // TODO Log.d(TAG, "onSslErrorEventReceive=" + JSON.stringify(event)) + this.onReceivedSslErrorEventReceive(event.handler, event.error) } onClientAuthenticationRequest = (event: Any) => { - // TODO Log.d(TAG, "onClientAuthenticationRequest=" + JSON.stringify(event)) + this.onReceivedClientAuthenticationRequest(event.handler, event.host, event.port, event.keyTypes, event.issuers) } onPermissionRequest = (event: Any) => { if (this.inAppWebView != null && this.inAppWebView.channelDelegate != null) { @@ -476,7 +486,7 @@ export default class InAppWebViewChromeClient { onContextMenuShow = (event: Any) => { // TODO Log.d(TAG, "onContextMenuShow=" + JSON.stringify(event)) - return false; + return true; } onContextMenuHide = () => { // TODO @@ -505,7 +515,13 @@ export default class InAppWebViewChromeClient { } } onFullScreenEnter = (event: Any) => { - // TODO 设置Ability进入全屏 这里缺少API获取当前window是否全屏状态 获取当前值 在exit时候 需要恢复到原来值。 + let context = this.inAppWebView.context as common.UIAbilityContext; + let windowClass = context.windowStage.getMainWindowSync(); + let windowProperties = windowClass.getWindowProperties(); + this.isOriginalLayoutFullScreen = windowProperties.isLayoutFullScreen; + this.isOriginalFullScreen = windowProperties.isFullScreen; + windowClass.setWindowLayoutFullScreen(true) + windowClass.setWindowSystemBarEnable([]) this.fullScreenExitHandler = event.handler Log.d(TAG, "onFullScreenEnter=" + JSON.stringify(event)) if (this.inAppWebView.channelDelegate != null) { @@ -515,7 +531,10 @@ export default class InAppWebViewChromeClient { } onFullScreenExit = () => { Log.d(TAG, "onFullScreenExit=") - // TODO 设置Ability退出全屏 + let context = this.inAppWebView.context as common.UIAbilityContext; + let windowClass = context.windowStage.getMainWindowSync(); + windowClass.setWindowLayoutFullScreen(this.isOriginalLayoutFullScreen) + windowClass.setWindowSystemBarEnable(this.isOriginalFullScreen ? [] : ['status', 'navigation']) if (this.fullScreenExitHandler) { this.fullScreenExitHandler.exitFullScreen() } @@ -526,21 +545,50 @@ export default class InAppWebViewChromeClient { } onWindowNew = (event: Any) => { Log.d(TAG, "onWindowNew=" + JSON.stringify(event)) + let windowId = 0; + if (this.plugin != null && this.plugin.inAppWebViewManager != null) { + this.plugin.inAppWebViewManager.windowAutoincrementId++; + windowId = this.plugin.inAppWebViewManager.windowAutoincrementId; + } + + let request = new URLRequest(event.targetUrl, "GET", null, new Map()); + let createWindowAction = new CreateWindowAction(request, true, event.isUserTrigger, false, windowId, event.isAlert); + if (this.plugin != null && this.plugin.inAppWebViewManager != null) { + this.plugin.inAppWebViewManager.windowWebViewMessages.set(windowId, event.handler); + } + if (this.inAppWebView.channelDelegate != null) { + this.inAppWebView.channelDelegate.onCreateWindow(createWindowAction, + new InnerCreateWindowCallback(this.inAppWebView, windowId)); + } } onWindowExit = () => { Log.d(TAG, "onWindowExit=") + if (this.inAppWebView.channelDelegate != null) { + this.inAppWebView.channelDelegate.onCloseWindow(); + } } onSearchResultReceive = (event: Any) => { Log.d(TAG, "onSearchResultReceive=" + JSON.stringify(event)) + // TODO } onDataResubmitted = (event: Any) => { Log.d(TAG, "onDataResubmitted=" + JSON.stringify(event)) + let callback = new InnerFormResubmissionCallback(event.handler); + if (this.inAppWebView.channelDelegate != null) { + this.inAppWebView.channelDelegate.onFormResubmission(this.inAppWebView!.controller!.getUrl(), callback); + } else { + callback.defaultBehaviour(null); + } } onPageVisible = (event: Any) => { Log.d(TAG, "onPageVisible=" + JSON.stringify(event)) + if (this.inAppWebView.channelDelegate != null) { + this.inAppWebView.channelDelegate.onPageCommitVisible(event.url); + } } onInterceptKeyEvent = (event: Any) => { Log.d(TAG, "onInterceptKeyEvent=" + JSON.stringify(event)) + // TODO return false; } onTouchIconUrlReceived = (event: Any) => { @@ -565,9 +613,11 @@ export default class InAppWebViewChromeClient { } onAudioStateChanged = (event: Any) => { Log.d(TAG, "onAudioStateChanged=" + JSON.stringify(event)) + // TODO } onFirstContentfulPaint = (event: Any) => { Log.d(TAG, "onFirstContentfulPaint=" + JSON.stringify(event)) + // TODO } onLoadIntercept = (event: Any) => { //对应安卓 shouldOverrideUrlLoading OHOS不知道异步 不知道如何适配了 // TODO @@ -588,24 +638,42 @@ export default class InAppWebViewChromeClient { } onRequestSelected = () => { Log.d(TAG, "onRequestSelected=") + if(this.inAppWebView.channelDelegate != null) { + this.inAppWebView.channelDelegate.onRequestFocus(); + } } onScreenCaptureRequest = (event: Any) => { Log.d(TAG, "onScreenCaptureRequest=" + JSON.stringify(event)) + // TODO } onOverScroll = (event: Any) => { + // TODO 没有clampedX clampedY? Log.d(TAG, "onOverScroll=" + JSON.stringify(event)) + if (this.inAppWebView.channelDelegate != null) { + this.inAppWebView.canScrollHorizontally({ + onReceiveValue(canScroll: boolean | null): void { + let overScrolledHorizontally: boolean = canScroll!; + let overScrolledVertically: boolean = this.inAppWebView.canScrollVertically(); + this.inAppWebView.channelDelegate.onOverScrolled(event.xOffset, event.yOffset, overScrolledHorizontally, overScrolledVertically); + } + }); + } } onNavigationEntryCommitted = () => { Log.d(TAG, "onNavigationEntryCommitted=") + // TODO } onSafeBrowsingCheckResult = () => { Log.d(TAG, "onSafeBrowsingCheckResult=") + // TODO } onNativeEmbedLifecycleChange = (callback: NativeEmbedDataInfo) => { Log.d(TAG, "onNativeEmbedLifecycleChange=") + // TODO } onNativeEmbedGestureEvent = (callback: NativeEmbedTouchInfo) => { Log.d(TAG, "onNativeEmbedGestureEvent=") + // TODO } private async onShouldOverrideUrlLoading(webView: InAppWebView, url: string, method: string, @@ -654,11 +722,13 @@ export default class InAppWebViewChromeClient { let certificate: cert.X509Cert | null = null; let certificates = await this.inAppWebView!.controller!.getCertificate(); - if(certificates && certificates.length > 0){ + if (certificates && certificates.length > 0) { certificate = certificates[0]; } let protectionSpace = new URLProtectionSpace(host, protocol, realm, port, null, certificate, null); - let challenge = new HttpAuthenticationChallenge(protectionSpace, InAppWebViewChromeClient.previousAuthRequestFailureCount, credentialProposed); + let challenge = + new HttpAuthenticationChallenge(protectionSpace, InAppWebViewChromeClient.previousAuthRequestFailureCount, + credentialProposed); let callback = new InnerReceivedHttpAuthRequestCallback(this.inAppWebView, handler, host, protocol, realm, port); if (this.inAppWebView.channelDelegate != null) { @@ -668,6 +738,62 @@ export default class InAppWebViewChromeClient { } } + private onReceivedSslErrorEventReceive(handler: SslErrorHandler, sslError: SslError) { + let url = this.inAppWebView!.controller!.getUrl(); + let host = ""; + let protocol = "https"; + let port = 0; + + try { + let uriurl = new uri.URI(url); + host = uriurl.host; + protocol = uriurl.scheme; + port = Number.parseInt(uriurl.port); + } catch (e) { + Log.e(TAG, "", e); + } + + // TODO sslError.getCertificate()没有这方法 用null先适配 + let protectionSpace = new URLProtectionSpace(host, protocol, null, port, null, null, sslError); + let challenge = new ServerTrustChallenge(protectionSpace); + let callback = new InnerReceivedServerTrustAuthRequestCallback(handler); + if (this.inAppWebView.channelDelegate != null) { + this.inAppWebView.channelDelegate.onReceivedServerTrustAuthRequest(challenge, callback); + } else { + callback.defaultBehaviour(null); + } + } + + private async onReceivedClientAuthenticationRequest(handler: ClientAuthenticationHandler, host: string, + port: number, keyTypes: Array, issuers: Array) { + let url = this.inAppWebView!.controller!.getUrl(); + let protocol = "https"; + + if (url != null) { + try { + let uriurl = new uri.URI(url); + protocol = uriurl.scheme; + } catch (e) { + Log.e(TAG, "", e); + } + } + + let certificate: cert.X509Cert | null = null; + let certificates = await this.inAppWebView!.controller!.getCertificate(); + if (certificates && certificates.length > 0) { + certificate = certificates[0]; + } + let protectionSpace = new URLProtectionSpace(host, protocol, null, port, null, certificate, null); + let challenge = new ClientCertChallenge(protectionSpace, issuers, keyTypes); + + let callback = new InnerReceivedClientCertRequestCallback(this.inAppWebView!, handler); + if (this.inAppWebView.channelDelegate != null) { + this.inAppWebView.channelDelegate.onReceivedClientCertRequest(challenge, callback); + } else { + callback.defaultBehaviour(null); + } + } + private loadCustomJavaScriptOnPageStarted(webView: InAppWebView) { let source = webView.userContentController.generateWrappedCodeForDocumentStart(); webView.controller.runJavaScriptExt(source) @@ -1101,7 +1227,8 @@ class InnerReceivedHttpAuthRequestCallback extends ReceivedHttpAuthRequestCallba private finalPort: number; private inAppWebView: InAppWebView; - constructor(inAppWebView: InAppWebView, handler: HttpAuthHandler, host: string, protocol: string, realm: string, port: number) { + constructor(inAppWebView: InAppWebView, handler: HttpAuthHandler, host: string, protocol: string, realm: string, + port: number) { super(); this.handler = handler; this.host = host; @@ -1120,7 +1247,8 @@ class InnerReceivedHttpAuthRequestCallback extends ReceivedHttpAuthRequestCallba let password = response.getPassword(); let permanentPersistence = response.isPermanentPersistence(); if (permanentPersistence) { - CredentialDatabase.getInstance(this.inAppWebView.context).setHttpAuthCredential(this.host, this.finalProtocol, this.realm, this.finalPort, username, password); + CredentialDatabase.getInstance(this.inAppWebView.context) + .setHttpAuthCredential(this.host, this.finalProtocol, this.realm, this.finalPort, username, password); } this.handler.confirm(username, password); break; @@ -1146,11 +1274,161 @@ class InnerReceivedHttpAuthRequestCallback extends ReceivedHttpAuthRequestCallba } defaultBehaviour(result: HttpAuthResponse | null): void { - this.handler.cancel(); + if (result == null) { + this.handler.cancel(); + } else { + this.nonNullSuccess(result) + } + } + + error(errorCode: string, errorMessage: string, errorDetails: Any): void { + Log.e(TAG, errorCode + ", " + ((errorMessage != null) ? errorMessage : "")); + this.defaultBehaviour(null); + } +} + +class InnerReceivedServerTrustAuthRequestCallback extends ReceivedServerTrustAuthRequestCallback { + private handler: SslErrorHandler; + + constructor(handler: SslErrorHandler) { + super(); + this.handler = handler; + } + + nonNullSuccess(response: ServerTrustAuthResponse): boolean { + let action = response.getAction(); + if (action != null) { + switch (action) { + case 1: + this.handler.handleConfirm(); + break; + case 0: + default: + this.handler.handleCancel(); + } + return false; + } + return true; + } + + defaultBehaviour(result: ServerTrustAuthResponse | null) { + if (result != null) { + this.nonNullSuccess(result); + } else { + this.handler.handleCancel(); + } + } + + error(errorCode: string, errorMessage: string, errorDetails: Any): void { + Log.e(TAG, errorCode + ", " + ((errorMessage != null) ? errorMessage : "")); + this.defaultBehaviour(null); + } +} + +class InnerReceivedClientCertRequestCallback extends ReceivedClientCertRequestCallback { + private handler: ClientAuthenticationHandler; + private inAppWebView: InAppWebView; + + constructor(inAppWebView: InAppWebView, handler: ClientAuthenticationHandler) { + super(); + this.inAppWebView = inAppWebView; + this.handler = handler; + } + + nonNullSuccess(response: ClientCertResponse): boolean { + let action = response.getAction(); + if (action != null && this.inAppWebView.plugin != null) { + switch (action) { + case 1: { + let certificatePath = response.getCertificatePath(); + let certificatePassword = response.getCertificatePassword(); + let keyStoreType = response.getKeyStoreType(); + //TODO priKeyFile? + this.handler.confirm(keyStoreType, certificatePath) + } + break; + case 2: + this.handler.ignore(); + break; + case 0: + default: + this.handler.cancel(); + } + return false; + } + return true; + } + + defaultBehaviour(result: ClientCertResponse | null) { + if (result != null) { + this.nonNullSuccess(result); + } else { + this.handler.cancel(); + } + } + + error(errorCode: string, errorMessage: string, errorDetails: Any): void { + Log.e(TAG, errorCode + ", " + ((errorMessage != null) ? errorMessage : "")); + this.defaultBehaviour(null); + } +} + +class InnerCreateWindowCallback extends CreateWindowCallback { + private finalWindowId: number; + private inAppWebView: InAppWebView; + + constructor(inAppWebView: InAppWebView, finalWindowId: number) { + super(); + this.inAppWebView = inAppWebView; + this.finalWindowId = finalWindowId; + } + + nonNullSuccess(handledByClient: boolean): boolean { + return !handledByClient; + } + + defaultBehaviour(handledByClient: boolean | null) { + if (this.inAppWebView.plugin != null && this.inAppWebView.plugin.inAppWebViewManager != null) { + this.inAppWebView.plugin.inAppWebViewManager.windowWebViewMessages.delete(this.finalWindowId); + } + } + + error(errorCode: string, errorMessage: string, errorDetails: Any): void { + Log.e(TAG, errorCode + ", " + ((errorMessage != null) ? errorMessage : "")); + this.defaultBehaviour(null); + } +} + +class InnerFormResubmissionCallback extends FormResubmissionCallback { + private hanlder: DataResubmissionHandler; + + constructor(hanlder: DataResubmissionHandler) { + super(); + this.hanlder = hanlder; + } + + nonNullSuccess(action: number): boolean { + switch (action) { + case 0: + this.hanlder.resend(); + break; + case 1: + default: + this.hanlder.cancel(); + } + return false; + } + + defaultBehaviour(result: number | null) { + if (result != null) { + this.nonNullSuccess(result); + } else { + this.hanlder.cancel(); + } } error(errorCode: string, errorMessage: string, errorDetails: Any): void { Log.e(TAG, errorCode + ", " + ((errorMessage != null) ? errorMessage : "")); this.defaultBehaviour(null); } -} \ No newline at end of file +}; \ No newline at end of file