From 44371def0a11a4dd1458b682d72da790fc604927 Mon Sep 17 00:00:00 2001 From: zhuzhengjun Date: Fri, 7 Jun 2024 17:10:38 +0800 Subject: [PATCH 1/4] =?UTF-8?q?=E6=B7=BB=E5=8A=A0web=E4=B8=8B=E6=8B=89?= =?UTF-8?q?=E5=88=B7=E6=96=B0=E5=92=8Cauthhttp?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zhuzhengjun --- .../lib/in_app_webiew_example.screen.dart | 4 +- .../ets/components/plugin/EventConstant.ts | 18 ++ .../CredentialDatabase.ets | 80 ++++++- .../CredentialDatabaseHandler.ets | 147 ++++++------ .../CredentialDatabaseHelper.ets | 35 ++- .../credential_database/URLCredentialDao.ets | 123 +++++----- .../URLProtectionSpaceDao.ets | 120 ++++------ .../PullToRefreshChannelDelegate.ets | 15 +- .../pull_to_refresh/PullToRefreshLayout.ets | 34 ++- .../pull_to_refresh/PullToRefreshSettings.ets | 14 +- .../plugin/types/URLProtectionSpace.ets | 21 +- .../plugin/types/WebViewAssetLoader.ets | 39 ++-- .../plugin/types/WebViewAssetLoaderExt.ets | 42 ++-- .../webview/in_app_webview/FlutterWebView.ets | 1 - .../webview/in_app_webview/InAppWebView.ets | 10 + .../InAppWebViewChromeClient.ets | 218 ++++++++++-------- .../webview/in_app_webview/OhosWebView.ets | 217 ++++++++++------- 17 files changed, 680 insertions(+), 458 deletions(-) create mode 100644 flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/EventConstant.ts diff --git a/flutter_inappwebview/example/lib/in_app_webiew_example.screen.dart b/flutter_inappwebview/example/lib/in_app_webiew_example.screen.dart index 79dc016f..8df15a82 100755 --- a/flutter_inappwebview/example/lib/in_app_webiew_example.screen.dart +++ b/flutter_inappwebview/example/lib/in_app_webiew_example.screen.dart @@ -63,7 +63,7 @@ class _InAppWebViewExampleScreenState extends State { }); pullToRefreshController = kIsWeb || - ![TargetPlatform.iOS, TargetPlatform.android] + ![TargetPlatform.iOS, TargetPlatform.android, TargetPlatform.ohos] .contains(defaultTargetPlatform) ? null : PullToRefreshController( @@ -71,7 +71,7 @@ class _InAppWebViewExampleScreenState extends State { color: Colors.blue, ), onRefresh: () async { - if (defaultTargetPlatform == TargetPlatform.android) { + if (defaultTargetPlatform == TargetPlatform.android || defaultTargetPlatform == TargetPlatform.ohos) { webViewController?.reload(); } else if (defaultTargetPlatform == TargetPlatform.iOS || defaultTargetPlatform == TargetPlatform.macOS) { diff --git a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/EventConstant.ts b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/EventConstant.ts new file mode 100644 index 00000000..df137f9b --- /dev/null +++ b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/EventConstant.ts @@ -0,0 +1,18 @@ +/* +* 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. +*/ + +export default class EventConstant { + public static readonly EVENT_PULL_SETREFRESHING = "pull_setRefreshing"; +} \ No newline at end of file diff --git a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/credential_database/CredentialDatabase.ets b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/credential_database/CredentialDatabase.ets index 41833264..8894f2ef 100644 --- a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/credential_database/CredentialDatabase.ets +++ b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/credential_database/CredentialDatabase.ets @@ -16,32 +16,94 @@ import CredentialDatabaseHelper from './CredentialDatabaseHelper' import URLCredentialDao from './URLCredentialDao' import URLProtectionSpaceDao from './URLProtectionSpaceDao' +import URLProtectionSpace from '../types/URLProtectionSpace' import common from '@ohos.app.ability.common'; +import URLCredential from '../types/URLCredential' +import List from '@ohos.util.List' const TAG = "CredentialDatabase" -const DATABASE_NAME = "CredentialDatabase.db" export default class CredentialDatabase { - - private static instance: CredentialDatabase = new CredentialDatabase(null, null, null) + private static instance: CredentialDatabase | null = null; public static DATABASE_VERSION: number = 2 + public static DATABASE_NAME: string = "CredentialDatabase.db"; + public protectionSpaceDao: URLProtectionSpaceDao + public credentialDao: URLCredentialDao + public db: CredentialDatabaseHelper - public protectionSpaceDao: URLProtectionSpaceDao | null - public credentialDao: URLCredentialDao | null - public db: CredentialDatabaseHelper | null - - constructor(db: CredentialDatabaseHelper | null, protectionSpaceDao: URLProtectionSpaceDao | null, credentialDao: URLCredentialDao | null) { + constructor(db: CredentialDatabaseHelper, protectionSpaceDao: URLProtectionSpaceDao, + credentialDao: URLCredentialDao) { this.db = db this.credentialDao = credentialDao this.protectionSpaceDao = protectionSpaceDao } public static getInstance(context: common.Context): CredentialDatabase { - if(CredentialDatabase.instance != null) + if (CredentialDatabase.instance != null) { return CredentialDatabase.instance + } let db: CredentialDatabaseHelper = new CredentialDatabaseHelper(context) CredentialDatabase.instance = new CredentialDatabase(db, new URLProtectionSpaceDao(db), new URLCredentialDao(db)) return CredentialDatabase.instance } + public async getHttpAuthCredentials(host: string, protocol: string, realm: string, port: number) { + let credentials: List = new List(); + let protectionSpace = await this.protectionSpaceDao.find(host, protocol, realm, port); + if (protectionSpace != null) { + credentials = await this.credentialDao.getAllByProtectionSpaceId(protectionSpace.getId()); + } + return credentials; + } + + public async setHttpAuthCredential(host: string, protocol: string, realm: string, port: number, username: string, + password: string) { + let protectionSpace = await this.protectionSpaceDao.find(host, protocol, realm, port); + let protectionSpaceId: number | null = null; + if (protectionSpace == null) { + protectionSpaceId = await this.protectionSpaceDao.insert(new URLProtectionSpace(host, protocol, realm, port)); + } else { + protectionSpaceId = protectionSpace.getId(); + + } + + let credential = await this.credentialDao.find(username, password, protectionSpaceId); + if (credential != null) { + let needUpdate = false; + if (credential.getUsername() != username) { + credential.setUsername(username); + needUpdate = true; + } + if (credential.getPassword() != password) { + credential.setPassword(password); + needUpdate = true; + } + if (needUpdate) { + await this.credentialDao.update(credential); + } + } else { + credential = new URLCredential(null, username, password, protectionSpaceId); + credential.setId(await this.credentialDao.insert(credential)); + } + } + + public async removeHttpAuthCredentials(host: string, protocol: string, realm: string, port: number) { + let URLProtectionSpace = await this.protectionSpaceDao.find(host, protocol, realm, port); + if (URLProtectionSpace != null) { + this.protectionSpaceDao.delete(URLProtectionSpace); + } + } + + public async removeHttpAuthCredential(host: string, protocol: string, realm: string, port: number, username: string, + password: string) { + let protectionSpace = await this.protectionSpaceDao.find(host, protocol, realm, port); + if (protectionSpace != null) { + let credential = await this.credentialDao.find(username, password, protectionSpace.getId()); + this.credentialDao.delete(credential); + } + } + + public clearAllAuthCredentials() { + this.db.clearAllTables(); + } } \ No newline at end of file diff --git a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/credential_database/CredentialDatabaseHandler.ets b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/credential_database/CredentialDatabaseHandler.ets index 961102d9..9e6d75e5 100644 --- a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/credential_database/CredentialDatabaseHandler.ets +++ b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/credential_database/CredentialDatabaseHandler.ets @@ -17,10 +17,9 @@ import { Any, MethodCall, MethodChannel } from '@ohos/flutter_ohos'; import InAppWebViewFlutterPlugin from '../InAppWebViewFlutterPlugin'; import ChannelDelegateImpl from '../types/ChannelDelegateImpl'; import CredentialDatabase from './CredentialDatabase'; -import common from '@ohos.app.ability.common'; import { MethodResult } from '@ohos/flutter_ohos/src/main/ets/plugin/common/MethodChannel'; import List from '@ohos.util.List'; -import URLProtectionSpace from '../types/URLProtectionSpace'; +import web_webview from '@ohos.web.webview' const TAG = "CredentialDatabaseHandler" const METHOD_CHANNEL_NAME = "com.pichillilorenzo/flutter_inappwebview_credential_database" @@ -47,94 +46,66 @@ export default class CredentialDatabaseHandler extends ChannelDelegateImpl { switch (call.method) { case "getAllAuthCredentials": - { - let allCredentials: List> = new List>(); - // if (this.credentialDatabase != null) { - // let protectionSpaces: List = credentialDatabase.protectionSpaceDao.getAll(); - // for (URLProtectionSpace protectionSpace : protectionSpaces) { - // List> credentials = new ArrayList<>(); - // for (URLCredential credential : credentialDatabase.credentialDao.getAllByProtectionSpaceId(protectionSpace.getId())) { - // credentials.add(credential.toMap()); - // } - // Map obj = new HashMap<>(); - // obj.put("protectionSpace", protectionSpace.toMap()); - // obj.put("credentials", credentials); - // allCredentials.add(obj); - // } - // } - result.success(allCredentials); + if (this.credentialDatabase != null) { + this.getAllAuthCredentials(result); + } else { + result.success(false); } break; case "getHttpAuthCredentials": - { - let credentials: List> = new List>(); - if (this.credentialDatabase != null) { - let host: string = call.argument("host") as string; - let protocol: string = call.argument("protocol") as string; - let realm: string = call.argument("realm") as string; - let port: number = call.argument("port") as number; - - // for (URLCredential credential : credentialDatabase.getHttpAuthCredentials(host, protocol, realm, port)) { - // credentials.add(credential.toMap()); - // } - } - result.success(credentials); + if (this.credentialDatabase != null) { + this.getHttpAuthCredentials(call, result); + } else { + result.success(false); } break; case "setHttpAuthCredential": - { - if (this.credentialDatabase != null) { - let host: string = call.argument("host") as string; - let protocol: string = call.argument("protocol") as string; - let realm: string = call.argument("realm") as string; - let port: number = call.argument("port") as number; - let username: string = call.argument("username") as string; - let password: string = call.argument("password") as string; - - // this.credentialDatabase.setHttpAuthCredential(host, protocol, realm, port, username, password); - result.success(true); - } else { - result.success(false); - } + if (this.credentialDatabase != null) { + let host: string = call.argument("host") as string; + let protocol: string = call.argument("protocol") as string; + let realm: string = call.argument("realm") as string; + let port: number = call.argument("port") as number; + let username: string = call.argument("username") as string; + let password: string = call.argument("password") as string; + this.credentialDatabase?.setHttpAuthCredential(host, protocol, realm, port, username, password); + result.success(true); + } else { + result.success(false); } break; case "removeHttpAuthCredential": - { - if (this.credentialDatabase != null) { - let host = call.argument("host") as string; - let protocol: string = call.argument("protocol") as string; - let realm: string = call.argument("realm") as string; - let port: number = call.argument("port") as number; - let username: string = call.argument("username") as string; - let password: string = call.argument("password") as string; + if (this.credentialDatabase != null) { + let host = call.argument("host") as string; + let protocol: string = call.argument("protocol") as string; + let realm: string = call.argument("realm") as string; + let port: number = call.argument("port") as number; + let username: string = call.argument("username") as string; + let password: string = call.argument("password") as string; - // this.credentialDatabase.removeHttpAuthCredential(host, protocol, realm, port, username, password); - result.success(true); - } else { - result.success(false); - } + this.credentialDatabase.removeHttpAuthCredential(host, protocol, realm, port, username, password); + result.success(true); + } else { + result.success(false); } break; case "removeHttpAuthCredentials": - { - if (this.credentialDatabase != null) { - let host: string = call.argument("host") as string; - let protocol: string = call.argument("protocol") as string; - let realm: string = call.argument("realm") as string; - let port: number = call.argument("port") as number; + if (this.credentialDatabase != null) { + let host: string = call.argument("host") as string; + let protocol: string = call.argument("protocol") as string; + let realm: string = call.argument("realm") as string; + let port: number = call.argument("port") as number; - // this.credentialDatabase.removeHttpAuthCredentials(host, protocol, realm, port); - result.success(true); - } else { - result.success(false); - } + this.credentialDatabase.removeHttpAuthCredentials(host, protocol, realm, port); + result.success(true); + } else { + result.success(false); } break; case "clearAllAuthCredentials": if (this.credentialDatabase != null) { - // this.credentialDatabase.clearAllAuthCredentials(); + this.credentialDatabase.clearAllAuthCredentials(); if (this.plugin != null && this.plugin.applicationContext != null) { - // WebViewDatabase.getInstance(this.plugin.applicationContext).clearHttpAuthUsernamePassword(); + web_webview.WebDataBase.deleteHttpAuthCredentials(); } result.success(true); } else { @@ -146,6 +117,40 @@ export default class CredentialDatabaseHandler extends ChannelDelegateImpl { } } + private async getAllAuthCredentials(result: MethodResult){ + let allCredentials: List> = new List>(); + if (this.credentialDatabase != null) { + let protectionSpaces = await this.credentialDatabase!.protectionSpaceDao.getAll(); + protectionSpaces.forEach(async (item) => { + let credentials: List> = new List>(); + let URLCredentials = await this.credentialDatabase!.credentialDao.getAllByProtectionSpaceId(item.getId()) + URLCredentials.forEach(credential => { + credentials.add(credential.toMap()); + }) + let obj : Map = new Map(); + obj.set("protectionSpace", item.toMap()); + obj.set("credentials", credentials); + allCredentials.add(obj); + }) + } + result.success(allCredentials); + } + + private async getHttpAuthCredentials(call: MethodCall, result: MethodResult) { + let credentials: List> = new List>(); + if (this.credentialDatabase != null) { + let host: string = call.argument("host") as string; + let protocol: string = call.argument("protocol") as string; + let realm: string = call.argument("realm") as string; + let port: number = call.argument("port") as number; + let URLCredentials = await this.credentialDatabase!.getHttpAuthCredentials(host, protocol, realm, port); + URLCredentials.forEach(credential => { + credentials.add(credential.toMap()); + }) + } + result.success(credentials); + } + public dispose(): void { super.dispose(); this.plugin = null; diff --git a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/credential_database/CredentialDatabaseHelper.ets b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/credential_database/CredentialDatabaseHelper.ets index 3e3ca0fa..4849d21f 100644 --- a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/credential_database/CredentialDatabaseHelper.ets +++ b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/credential_database/CredentialDatabaseHelper.ets @@ -15,11 +15,13 @@ import URLCredentialContract from './URLCredentialContract'; import URLProtectionSpaceContract from './URLProtectionSpaceContract'; +import CredentialDatabase from './CredentialDatabase'; import { Context } from '@kit.AbilityKit'; +import data_rdb from '@ohos.data.relationalStore' export default class CredentialDatabaseHelper { private static SQL_CREATE_PROTECTION_SPACE_TABLE: string = - "CREATE TABLE " + URLProtectionSpaceContract.TABLE_NAME + " (" + + "CREATE TABLE IF NOT EXISTS " + URLProtectionSpaceContract.TABLE_NAME + " (" + URLProtectionSpaceContract._ID + " INTEGER PRIMARY KEY," + URLProtectionSpaceContract.COLUMN_NAME_HOST + " TEXT NOT NULL," + URLProtectionSpaceContract.COLUMN_NAME_PROTOCOL + " TEXT," + @@ -31,7 +33,7 @@ export default class CredentialDatabaseHelper { ");"; private static SQL_CREATE_CREDENTIAL_TABLE: string = - "CREATE TABLE " + URLCredentialContract.TABLE_NAME + " (" + + "CREATE TABLE IF NOT EXISTS " + URLCredentialContract.TABLE_NAME + " (" + URLCredentialContract._ID + " INTEGER PRIMARY KEY," + URLCredentialContract.COLUMN_NAME_USERNAME + " TEXT NOT NULL," + URLCredentialContract.COLUMN_NAME_PASSWORD + " TEXT NOT NULL," + @@ -49,5 +51,32 @@ export default class CredentialDatabaseHelper { private static SQL_DELETE_CREDENTIAL_TABLE: string = "DROP TABLE IF EXISTS " + URLCredentialContract.TABLE_NAME; - constructor(context: Context) {} + private rdbStore: data_rdb.RdbStore | null = null; + private context : Context; + + constructor(context: Context) { + this.context = context; + } + + private async initRdb() { + if (this.rdbStore != null) { + return + } + this.rdbStore = await data_rdb.getRdbStore(this.context, { + name: CredentialDatabase.DATABASE_NAME, securityLevel: data_rdb.SecurityLevel.S1 + }) + await this.rdbStore.executeSql(CredentialDatabaseHelper.SQL_CREATE_PROTECTION_SPACE_TABLE); + await this.rdbStore.executeSql(CredentialDatabaseHelper.SQL_CREATE_CREDENTIAL_TABLE); + } + + async clearAllTables() { + await this.initRdb(); + await this.rdbStore?.executeSql(CredentialDatabaseHelper.SQL_DELETE_PROTECTION_SPACE_TABLE); + await this.rdbStore?.executeSql(CredentialDatabaseHelper.SQL_DELETE_CREDENTIAL_TABLE); + } + + async getRdbStore() { + await this.initRdb(); + return this.rdbStore!; + } } \ No newline at end of file diff --git a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/credential_database/URLCredentialDao.ets b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/credential_database/URLCredentialDao.ets index 1c732576..019a87a1 100644 --- a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/credential_database/URLCredentialDao.ets +++ b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/credential_database/URLCredentialDao.ets @@ -17,6 +17,7 @@ import URLCredential from '../types/URLCredential' import CredentialDatabaseHelper from './CredentialDatabaseHelper' import URLCredentialContract from './URLCredentialContract' import List from '@ohos.util.List' +import { relationalStore } from '@kit.ArkData' export default class URLCredentialDao { credentialDatabaseHelper: CredentialDatabaseHelper @@ -31,89 +32,69 @@ export default class URLCredentialDao { this.credentialDatabaseHelper = credentialDatabaseHelper } - public getAllByProtectionSpaceId(protectionSpaceId: number): List { - let selection: string = URLCredentialContract.COLUMN_NAME_PROTECTION_SPACE_ID + " = ?"; - let selectionArgs: string[] = [protectionSpaceId.toString()] + public async getAllByProtectionSpaceId(protectionSpaceId: number) { let URLCredentials: List = new List(); - - //TODO - // Cursor cursor = credentialDatabaseHelper.getReadableDatabase().query( - // URLCredentialContract.FeedEntry.TABLE_NAME, - // projection, - // selection, - // selectionArgs, - // null, - // null, - // null - // ); - // while (cursor.moveToNext()) { - // Long id = cursor.getLong(cursor.getColumnIndexOrThrow(URLCredentialContract.FeedEntry._ID)); - // String username = cursor.getString(cursor.getColumnIndexOrThrow(URLCredentialContract.FeedEntry.COLUMN_NAME_USERNAME)); - // String password = cursor.getString(cursor.getColumnIndexOrThrow(URLCredentialContract.FeedEntry.COLUMN_NAME_PASSWORD)); - // URLCredentials.add(new URLCredential(id, username, password, protectionSpaceId)); - // } - // cursor.close(); + let predicates = new relationalStore.RdbPredicates(URLCredentialContract.TABLE_NAME); + predicates.equalTo(URLCredentialContract.COLUMN_NAME_PROTECTION_SPACE_ID, protectionSpaceId.toString()); + let rdbStore = await this.credentialDatabaseHelper.getRdbStore(); + let resultSet = await rdbStore.query(predicates); + while (resultSet.goToNextRow()) { + const id = resultSet.getLong(resultSet.getColumnIndex(URLCredentialContract._ID)); + const username = resultSet.getString(resultSet.getColumnIndex(URLCredentialContract.COLUMN_NAME_USERNAME)); + const password = resultSet.getString(resultSet.getColumnIndex(URLCredentialContract.COLUMN_NAME_PASSWORD)); + URLCredentials.add(new URLCredential(id, username, password, protectionSpaceId)); + } + resultSet.close(); return URLCredentials } - public find(username: string, password: string, protectionSpaceId: number): URLCredential | null { - //TODO - // String selection = URLCredentialContract.FeedEntry.COLUMN_NAME_USERNAME + " = ? AND " + - // URLCredentialContract.FeedEntry.COLUMN_NAME_PASSWORD + " = ? AND " + - // URLCredentialContract.FeedEntry.COLUMN_NAME_PROTECTION_SPACE_ID + " = ?"; - // String[] selectionArgs = {username, password, protectionSpaceId.toString()}; - // - // Cursor cursor = credentialDatabaseHelper.getReadableDatabase().query( - // URLCredentialContract.FeedEntry.TABLE_NAME, - // projection, - // selection, - // selectionArgs, - // null, - // null, - // null - // ); + public async find(username: string, password: string, protectionSpaceId: number){ + let predicates = new relationalStore.RdbPredicates(URLCredentialContract.TABLE_NAME); + predicates.equalTo(URLCredentialContract.COLUMN_NAME_USERNAME, username); + predicates.and(); + predicates.equalTo(URLCredentialContract.COLUMN_NAME_PASSWORD, password); + predicates.and(); + predicates.equalTo(URLCredentialContract.COLUMN_NAME_PROTECTION_SPACE_ID, protectionSpaceId.toString()); + let dbStore = await this.credentialDatabaseHelper.getRdbStore(); + let resultSet = await dbStore.query(predicates); - let URLCredential: URLCredential | null = null; - // if (cursor.moveToNext()) { - // Long rowId = cursor.getLong(cursor.getColumnIndexOrThrow(URLCredentialContract.FeedEntry._ID)); - // String rowUsername = cursor.getString(cursor.getColumnIndexOrThrow(URLCredentialContract.FeedEntry.COLUMN_NAME_USERNAME)); - // String rowPassword = cursor.getString(cursor.getColumnIndexOrThrow(URLCredentialContract.FeedEntry.COLUMN_NAME_PASSWORD)); - // URLCredential = new URLCredential(rowId, rowUsername, rowPassword, protectionSpaceId); - // } - // cursor.close(); + let urlCredential: URLCredential | null = null; + if (resultSet.goToNextRow()) { + const rowId = resultSet.getLong(resultSet.getColumnIndex(URLCredentialContract._ID)); + const rowUsername = resultSet.getString(resultSet.getColumnIndex(URLCredentialContract.COLUMN_NAME_USERNAME)); + const rowPassword = resultSet.getString(resultSet.getColumnIndex(URLCredentialContract.COLUMN_NAME_PASSWORD)); + urlCredential = new URLCredential(rowId, rowUsername, rowPassword, protectionSpaceId); + } + resultSet.close(); - return URLCredential; + return urlCredential; } - public insert(urlCredential: URLCredential): number { - //TODO - // let credentialValues: ContentValues = new ContentValues(); - // credentialValues.put(URLCredentialContract.FeedEntry.COLUMN_NAME_USERNAME, urlCredential.getUsername()); - // credentialValues.put(URLCredentialContract.FeedEntry.COLUMN_NAME_PASSWORD, urlCredential.getPassword()); - // credentialValues.put(URLCredentialContract.FeedEntry.COLUMN_NAME_PROTECTION_SPACE_ID, urlCredential.getProtectionSpaceId()); - // - // return credentialDatabaseHelper.getWritableDatabase().insert(URLCredentialContract.FeedEntry.TABLE_NAME, null, credentialValues); - return 0; + public async insert(urlCredential: URLCredential) { + const valueBucket: relationalStore.ValuesBucket = {}; + valueBucket[URLCredentialContract.COLUMN_NAME_USERNAME] = urlCredential.getUsername(); + valueBucket[URLCredentialContract.COLUMN_NAME_PASSWORD] = urlCredential.getPassword(); + valueBucket[URLCredentialContract.COLUMN_NAME_PROTECTION_SPACE_ID] = urlCredential.getProtectionSpaceId(); + let rdbStore = await this.credentialDatabaseHelper.getRdbStore(); + return await rdbStore.insert(URLCredentialContract.TABLE_NAME, valueBucket); } + public async update(urlCredential: URLCredential) { + const valueBucket: relationalStore.ValuesBucket = {}; + valueBucket[URLCredentialContract.COLUMN_NAME_USERNAME] = urlCredential.getUsername(); + valueBucket[URLCredentialContract.COLUMN_NAME_PASSWORD] = urlCredential.getPassword(); + + let predicates = new relationalStore.RdbPredicates(URLCredentialContract.TABLE_NAME); + predicates.equalTo(URLCredentialContract.COLUMN_NAME_PROTECTION_SPACE_ID, urlCredential.getProtectionSpaceId()?.toString()); - public update( urlCredential: URLCredential): number { - //TODO - // ContentValues credentialValues = new ContentValues(); - // credentialValues.put(URLCredentialContract.FeedEntry.COLUMN_NAME_USERNAME, urlCredential.getUsername()); - // credentialValues.put(URLCredentialContract.FeedEntry.COLUMN_NAME_PASSWORD, urlCredential.getPassword()); - // - // String whereClause = URLCredentialContract.FeedEntry.COLUMN_NAME_PROTECTION_SPACE_ID + " = ?"; - // String[] whereArgs = {urlCredential.getProtectionSpaceId().toString()}; - // - // return credentialDatabaseHelper.getWritableDatabase().update(URLCredentialContract.FeedEntry.TABLE_NAME, credentialValues, whereClause, whereArgs); - return 0; + let rdbStore = await this.credentialDatabaseHelper.getRdbStore(); + return rdbStore.update(valueBucket, predicates); } - public delete( urlCredential: URLCredential): number { - let whereClause: string = URLCredentialContract._ID + " = ?"; - let whereArgs = [urlCredential.getId()?.toString()]; - // return this.credentialDatabaseHelper.getWritableDatabase().delete(URLCredentialContract.TABLE_NAME, whereClause, whereArgs); - return 0; + public async delete( urlCredential: URLCredential) { + let predicates = new relationalStore.RdbPredicates(URLCredentialContract.TABLE_NAME); + predicates.equalTo(URLCredentialContract._ID, urlCredential.getId()?.toString()); + let rdbStore = await this.credentialDatabaseHelper.getRdbStore(); + return rdbStore.delete(predicates); } } \ No newline at end of file diff --git a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/credential_database/URLProtectionSpaceDao.ets b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/credential_database/URLProtectionSpaceDao.ets index 629bf0ac..efd4c81c 100644 --- a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/credential_database/URLProtectionSpaceDao.ets +++ b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/credential_database/URLProtectionSpaceDao.ets @@ -16,6 +16,7 @@ import URLProtectionSpace from '../types/URLProtectionSpace'; import CredentialDatabaseHelper from './CredentialDatabaseHelper'; import URLProtectionSpaceContract from './URLProtectionSpaceContract'; +import { relationalStore } from '@kit.ArkData'; export default class URLProtectionSpaceDao { credentialDatabaseHelper: CredentialDatabaseHelper @@ -31,84 +32,65 @@ export default class URLProtectionSpaceDao { this.credentialDatabaseHelper = credentialDatabaseHelper } - public getAll(): Array { + public async getAll() { let URLProtectionSpaces: Array = new Array(); - //TODO - // SQLiteDatabase readableDatabase = credentialDatabaseHelper.getReadableDatabase(); - // Cursor cursor = readableDatabase.query( - // URLProtectionSpaceContract.FeedEntry.TABLE_NAME, - // projection, - // null, - // null, - // null, - // null, - // null - // ); - // while (cursor.moveToNext()) { - // Long rowId = cursor.getLong(cursor.getColumnIndexOrThrow(URLProtectionSpaceContract.FeedEntry._ID)); - // String rowHost = cursor.getString(cursor.getColumnIndexOrThrow(URLProtectionSpaceContract.FeedEntry.COLUMN_NAME_HOST)); - // String rowProtocol = cursor.getString(cursor.getColumnIndexOrThrow(URLProtectionSpaceContract.FeedEntry.COLUMN_NAME_PROTOCOL)); - // String rowRealm = cursor.getString(cursor.getColumnIndexOrThrow(URLProtectionSpaceContract.FeedEntry.COLUMN_NAME_REALM)); - // Integer rowPort = cursor.getInt(cursor.getColumnIndexOrThrow(URLProtectionSpaceContract.FeedEntry.COLUMN_NAME_PORT)); - // URLProtectionSpaces.add(new URLProtectionSpace(rowId, rowHost, rowProtocol, rowRealm, rowPort)); - // } - // cursor.close(); + let predicates = new relationalStore.RdbPredicates(URLProtectionSpaceContract.TABLE_NAME); + let rdbStore = await this.credentialDatabaseHelper.getRdbStore(); + let resultSet = await rdbStore.query(predicates, this.projection); + while (resultSet.goToNextRow()) { + const rowId = resultSet.getLong(resultSet.getColumnIndex(URLProtectionSpaceContract._ID)); + const rowHost = resultSet.getString(resultSet.getColumnIndex(URLProtectionSpaceContract.COLUMN_NAME_HOST)); + const rowProtocol = resultSet.getString(resultSet.getColumnIndex(URLProtectionSpaceContract.COLUMN_NAME_PROTOCOL)); + const rowRealm = resultSet.getString(resultSet.getColumnIndex(URLProtectionSpaceContract.COLUMN_NAME_REALM)); + const rowPort = resultSet.getLong(resultSet.getColumnIndex(URLProtectionSpaceContract.COLUMN_NAME_PORT)); + URLProtectionSpaces.push(new URLProtectionSpace(rowHost, rowProtocol, rowRealm, rowPort, rowId)); + } + resultSet.close(); return URLProtectionSpaces; } - public find(host: string, protocol: string, realm: string, port: number): URLProtectionSpace | null { - //TODO - // SQLiteDatabase readableDatabase = credentialDatabaseHelper.getReadableDatabase(); - // - // String selection = URLProtectionSpaceContract.FeedEntry.COLUMN_NAME_HOST + " = ? AND " + URLProtectionSpaceContract.FeedEntry.COLUMN_NAME_PROTOCOL + " = ? AND " + - // URLProtectionSpaceContract.FeedEntry.COLUMN_NAME_REALM + " = ? AND " + URLProtectionSpaceContract.FeedEntry.COLUMN_NAME_PORT + " = ?"; - // String[] selectionArgs = {host, protocol, realm, port.toString()}; - // - // Cursor cursor = readableDatabase.query( - // URLProtectionSpaceContract.FeedEntry.TABLE_NAME, - // projection, - // selection, - // selectionArgs, - // null, - // null, - // null - // ); - // - // URLProtectionSpace URLProtectionSpace = null; - // if (cursor.moveToNext()) { - // Long rowId = cursor.getLong(cursor.getColumnIndexOrThrow(URLProtectionSpaceContract.FeedEntry._ID)); - // String rowHost = cursor.getString(cursor.getColumnIndexOrThrow(URLProtectionSpaceContract.FeedEntry.COLUMN_NAME_HOST)); - // String rowProtocol = cursor.getString(cursor.getColumnIndexOrThrow(URLProtectionSpaceContract.FeedEntry.COLUMN_NAME_PROTOCOL)); - // String rowRealm = cursor.getString(cursor.getColumnIndexOrThrow(URLProtectionSpaceContract.FeedEntry.COLUMN_NAME_REALM)); - // Integer rowPort = cursor.getInt(cursor.getColumnIndexOrThrow(URLProtectionSpaceContract.FeedEntry.COLUMN_NAME_PORT)); - // URLProtectionSpace = new URLProtectionSpace(rowId, rowHost, rowProtocol, rowRealm, rowPort); - // } - // cursor.close(); - // - // return URLProtectionSpace; - return null; + public async find(host: string, protocol: string, realm: string, port: number) { + let predicates = new relationalStore.RdbPredicates(URLProtectionSpaceContract.TABLE_NAME); + predicates.equalTo(URLProtectionSpaceContract.COLUMN_NAME_HOST, host); + predicates.and(); + predicates.equalTo(URLProtectionSpaceContract.COLUMN_NAME_PROTOCOL, protocol); + predicates.and(); + predicates.equalTo(URLProtectionSpaceContract.COLUMN_NAME_REALM, realm); + predicates.and(); + predicates.equalTo(URLProtectionSpaceContract.COLUMN_NAME_PORT, port.toString()); + + let dbStore = await this.credentialDatabaseHelper.getRdbStore(); + let resultSet = await dbStore.query(predicates); + + let urlProtectionSpace: URLProtectionSpace | null = null; + if (resultSet.goToNextRow()) { + const rowId = resultSet.getLong(resultSet.getColumnIndex(URLProtectionSpaceContract._ID)); + const rowHost = resultSet.getString(resultSet.getColumnIndex(URLProtectionSpaceContract.COLUMN_NAME_HOST)); + const rowProtocol = resultSet.getString(resultSet.getColumnIndex(URLProtectionSpaceContract.COLUMN_NAME_PROTOCOL)); + const rowRealm = resultSet.getString(resultSet.getColumnIndex(URLProtectionSpaceContract.COLUMN_NAME_REALM)); + const rowPort = resultSet.getLong(resultSet.getColumnIndex(URLProtectionSpaceContract.COLUMN_NAME_PORT)); + urlProtectionSpace = new URLProtectionSpace(rowHost, rowProtocol, rowRealm, rowPort, rowId); + } + resultSet.close(); + return urlProtectionSpace; } - public insert(URLProtectionSpace: URLProtectionSpace): number { - //TODO - // ContentValues protectionSpaceValues = new ContentValues(); - // protectionSpaceValues.put(URLProtectionSpaceContract.FeedEntry.COLUMN_NAME_HOST, URLProtectionSpace.getHost()); - // protectionSpaceValues.put(URLProtectionSpaceContract.FeedEntry.COLUMN_NAME_PROTOCOL, URLProtectionSpace.getProtocol()); - // protectionSpaceValues.put(URLProtectionSpaceContract.FeedEntry.COLUMN_NAME_REALM, URLProtectionSpace.getRealm()); - // protectionSpaceValues.put(URLProtectionSpaceContract.FeedEntry.COLUMN_NAME_PORT, URLProtectionSpace.getPort()); - // - // return credentialDatabaseHelper.getWritableDatabase().insert(URLProtectionSpaceContract.FeedEntry.TABLE_NAME, null, protectionSpaceValues); - return 0; + public async insert(URLProtectionSpace: URLProtectionSpace) { + const valueBucket: relationalStore.ValuesBucket = {}; + valueBucket[URLProtectionSpaceContract.COLUMN_NAME_HOST] = URLProtectionSpace.getHost(); + valueBucket[URLProtectionSpaceContract.COLUMN_NAME_PROTOCOL] = URLProtectionSpace.getProtocol(); + valueBucket[URLProtectionSpaceContract.COLUMN_NAME_REALM] = URLProtectionSpace.getRealm(); + valueBucket[URLProtectionSpaceContract.COLUMN_NAME_PORT] = URLProtectionSpace.getPort(); + let rdbStore = await this.credentialDatabaseHelper.getRdbStore(); + return await rdbStore.insert(URLProtectionSpaceContract.TABLE_NAME, valueBucket); } - public delete(URLProtectionSpace: URLProtectionSpace): number { - //TODO - // String whereClause = URLProtectionSpaceContract.FeedEntry._ID + " = ?"; - // String[] whereArgs = {URLProtectionSpace.getId().toString()}; - // - // return credentialDatabaseHelper.getWritableDatabase().delete(URLProtectionSpaceContract.FeedEntry.TABLE_NAME, whereClause, whereArgs); - return 0; + public async delete(URLProtectionSpace: URLProtectionSpace) { + let predicates = new relationalStore.RdbPredicates(URLProtectionSpaceContract.TABLE_NAME); + predicates.equalTo(URLProtectionSpaceContract._ID, URLProtectionSpace.getId()?.toString()); + let rdbStore = await this.credentialDatabaseHelper.getRdbStore(); + return rdbStore.delete(predicates); } } \ No newline at end of file diff --git a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/pull_to_refresh/PullToRefreshChannelDelegate.ets b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/pull_to_refresh/PullToRefreshChannelDelegate.ets index 706f48ef..374f28e3 100644 --- a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/pull_to_refresh/PullToRefreshChannelDelegate.ets +++ b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/pull_to_refresh/PullToRefreshChannelDelegate.ets @@ -32,7 +32,7 @@ export default class PullToRefreshChannelDelegate extends ChannelDelegateImpl { if (this.pullToRefreshView != null) { let enabled: boolean = call.argument("enabled") as boolean; this.pullToRefreshView.settings.enabled = enabled; // used by InAppWebView.onOverScrolled - // this.pullToRefreshView.setEnabled(enabled); + this.pullToRefreshView.setEnabled(enabled); result.success(true); } else { result.success(false); @@ -40,7 +40,7 @@ export default class PullToRefreshChannelDelegate extends ChannelDelegateImpl { break; case "isEnabled": if (this.pullToRefreshView != null) { - // result.success(this.pullToRefreshView.isEnabled()); + result.success(this.pullToRefreshView.isEnabled()); } else { result.success(false); } @@ -48,18 +48,19 @@ export default class PullToRefreshChannelDelegate extends ChannelDelegateImpl { case "setRefreshing": if (this.pullToRefreshView != null) { let refreshing: boolean = call.argument("refreshing") as boolean; - // this.pullToRefreshView.setRefreshing(refreshing); + this.pullToRefreshView.setRefreshing(refreshing); result.success(true); } else { result.success(false); } break; case "isRefreshing": - // result.success(this.pullToRefreshView != null && this.pullToRefreshView.isRefreshing()); + result.success(this.pullToRefreshView != null && this.pullToRefreshView.isRefreshing()); break; case "setColor": if (this.pullToRefreshView != null) { let color: string = call.argument("color"); + // TODO // this.pullToRefreshView.setColorSchemeColors(Color.parseColor(color)); result.success(true); } else { @@ -69,6 +70,7 @@ export default class PullToRefreshChannelDelegate extends ChannelDelegateImpl { case "setBackgroundColor": if (this.pullToRefreshView != null) { let color: string = call.argument("color"); + // TODO // this.pullToRefreshView.setProgressBackgroundColorSchemeColor(Color.parseColor(color)); result.success(true); } else { @@ -78,6 +80,7 @@ export default class PullToRefreshChannelDelegate extends ChannelDelegateImpl { case "setDistanceToTriggerSync": if (this.pullToRefreshView != null) { let distanceToTriggerSync: number = call.argument("distanceToTriggerSync"); + // TODO // this.pullToRefreshView.setDistanceToTriggerSync(distanceToTriggerSync); result.success(true); } else { @@ -87,6 +90,7 @@ export default class PullToRefreshChannelDelegate extends ChannelDelegateImpl { case "setSlingshotDistance": if (this.pullToRefreshView != null) { let slingshotDistance: number = call.argument("slingshotDistance"); + // TODO // this.pullToRefreshView.setSlingshotDistance(slingshotDistance); result.success(true); } else { @@ -94,11 +98,14 @@ export default class PullToRefreshChannelDelegate extends ChannelDelegateImpl { } break; case "getDefaultSlingshotDistance": + // TODO // result.success(SwipeRefreshLayout.DEFAULT_SLINGSHOT_DISTANCE); + result.success(100) break; case "setSize": if (this.pullToRefreshView != null) { let size: number = call.argument("size"); + // TODO // this.pullToRefreshView.setSize(size); result.success(true); } else { diff --git a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/pull_to_refresh/PullToRefreshLayout.ets b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/pull_to_refresh/PullToRefreshLayout.ets index 29840c07..eb2d8ecf 100644 --- a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/pull_to_refresh/PullToRefreshLayout.ets +++ b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/pull_to_refresh/PullToRefreshLayout.ets @@ -14,11 +14,13 @@ */ import { Any, MethodChannel } from '@ohos/flutter_ohos'; +import common from '@ohos.app.ability.common'; import InAppWebViewFlutterPlugin from '../InAppWebViewFlutterPlugin'; import { Disposable } from '../types/Disposable'; import PullToRefreshChannelDelegate from './PullToRefreshChannelDelegate'; import PullToRefreshSettings from './PullToRefreshSettings'; import InAppWebView from '../webview/in_app_webview/InAppWebView'; +import EventConstant from '../EventConstant' const LOG_TAG = "PullToRefreshLayout"; const METHOD_CHANNEL_NAME_PREFIX = "com.pichillilorenzo/flutter_inappwebview_pull_to_refresh_"; @@ -35,12 +37,38 @@ export default class PullToRefreshLayout implements Disposable { this.channelDelegate = new PullToRefreshChannelDelegate(this, channel); } - addView(webView: InAppWebView | null): void { - this.webView = webView + setEnabled(enable: boolean) { + + } + + isEnabled(): boolean { + return this.settings.enabled + } + + setRefreshing(refreshing: boolean) { + let context = this.webView!.context as common.UIAbilityContext; + context.eventHub.emit(EventConstant.EVENT_PULL_SETREFRESHING, refreshing) + } + + isRefreshing(): boolean { + return false + } + + onRefresh() { + if (this.channelDelegate == null) { + this.setRefreshing(false); + return; + } + this.channelDelegate!!.onRefresh(); + } + + addView(webView: InAppWebView): void { + this.webView = webView; + webView.setPullToRefreshLayout(this); } public prepare(): void { - if(this.webView != null) { + if (this.webView != null) { this.webView.refresh() this.webView.scrollToTop() } diff --git a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/pull_to_refresh/PullToRefreshSettings.ets b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/pull_to_refresh/PullToRefreshSettings.ets index 2c63f2e8..ae7b2d9b 100644 --- a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/pull_to_refresh/PullToRefreshSettings.ets +++ b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/pull_to_refresh/PullToRefreshSettings.ets @@ -35,25 +35,25 @@ export default class PullToRefreshSettings implements ISettings { let urlProtectionSpaceMap: Map = new Map(); urlProtectionSpaceMap.set("host", this.host); @@ -94,7 +103,7 @@ export default class URLProtectionSpace { } public getSslCertificate(): SslCertificate | null { - return this. sslCertificate; + return this.sslCertificate; } public setSslCertificate(sslCertificateExt: SslCertificate | null): void { diff --git a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/types/WebViewAssetLoader.ets b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/types/WebViewAssetLoader.ets index 5f296f6e..e5ab225f 100644 --- a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/types/WebViewAssetLoader.ets +++ b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/types/WebViewAssetLoader.ets @@ -22,7 +22,7 @@ import MimeUtil from './MimeUtil'; const TAG = "WebViewAssetLoader"; export interface PathHandler { - handle(path: string): Promise; + handle(path: string): WebResourceResponse; } //读取rawfile目录文件 @@ -33,12 +33,14 @@ export class AssetsPathHandler implements PathHandler { this.context = context; } - async handle(path: string): Promise { + handle(path: string): WebResourceResponse { let webResponse = new WebResourceResponse(); try { - let contentData = await this.context.resourceManager.getRawFileContent(path); - webResponse.setResponseData(contentData); - webResponse.setResponseMimeType(MimeUtil.guessMimeType(path)); + this.context.resourceManager.getRawFileContent(path).then(contentData => { + webResponse.setResponseData(contentData); + webResponse.setResponseMimeType(MimeUtil.guessMimeType(path)); + webResponse.setResponseIsReady(true); + }) } catch (e) { Log.e(TAG, "Error opening asset path: " + path, e); } @@ -54,12 +56,14 @@ export class ResourcesPathHandler implements PathHandler { this.context = context; } - async handle(path: string): Promise { + handle(path: string): WebResourceResponse { let webResponse = new WebResourceResponse(); try { - let contentData = await this.context.resourceManager.getRawFileContent(path); - webResponse.setResponseData(contentData); - webResponse.setResponseMimeType(MimeUtil.guessMimeType(path)); + this.context.resourceManager.getRawFileContent(path).then(contentData => { + webResponse.setResponseData(contentData); + webResponse.setResponseMimeType(MimeUtil.guessMimeType(path)); + webResponse.setResponseIsReady(true); + }); } catch (e) { Log.e(TAG, "Error opening asset path: " + path, e); } @@ -77,15 +81,16 @@ export class InternalStoragePathHandler implements PathHandler { this.directory = directory.endsWith("/") ? directory : (directory + "/"); } - async handle(path: string): Promise { + handle(path: string): WebResourceResponse { let webResponse = new WebResourceResponse(); try { let stream = fs.createStreamSync(this.directory + path, "r+") let arrayBuffer = new ArrayBuffer(4096); - let readLen = await stream.read(arrayBuffer); + let readLen = stream.readSync(arrayBuffer); let contentData = buffer.from(arrayBuffer, 0, readLen).buffer webResponse.setResponseData(contentData); webResponse.setResponseMimeType(MimeUtil.guessMimeType(path)); + webResponse.setResponseIsReady(true); } catch (e) { Log.e(TAG, "Error opening asset path: " + path, e); } @@ -146,15 +151,19 @@ export default class WebViewAssetLoader { this.mMatchers = pathMatchers; } - async shouldInterceptRequest(url: uri.URI) { + shouldInterceptRequest(url: uri.URI) { for (let matcher of this.mMatchers) { let handler = matcher.match(url); // The requested URL doesn't match the URL where this handler has been registered. - if (handler == null) continue; + if (handler == null) { + continue; + } let suffixPath = matcher.getSuffixPath(url.path); - let response = await handler.handle(suffixPath); + let response = handler.handle(suffixPath); // Handler doesn't want to intercept this request, try next handler. - if (response == null) continue; + if (response == null) { + continue; + } return response; } return null; diff --git a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/types/WebViewAssetLoaderExt.ets b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/types/WebViewAssetLoaderExt.ets index bf04e20b..9c802e39 100644 --- a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/types/WebViewAssetLoaderExt.ets +++ b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/types/WebViewAssetLoaderExt.ets @@ -39,7 +39,8 @@ export default class WebViewAssetLoaderExt implements Disposable { this.customPathHandlers = customPathHandlers; } - static fromMap(map: Map | null, plugin: InAppWebViewFlutterPlugin, context: Context): WebViewAssetLoaderExt | null { + static fromMap(map: Map | null, plugin: InAppWebViewFlutterPlugin, + context: Context): WebViewAssetLoaderExt | null { if (map == null) { return null; } @@ -110,26 +111,27 @@ class PathHandlerExt implements PathHandler, Disposable { this.channelDelegate = new PathHandlerExtChannelDelegate(this, channel); } - async handle(path: string): Promise { + handle(path: string): WebResourceResponse { + let webResourceResponse = new WebResourceResponse() if (this.channelDelegate != null) { - let response: WebResourceResponseExt | null = null; try { - response = await this.channelDelegate.handleSync(path); + this.channelDelegate.handleSync(path).then(response => { + if (response != null) { + webResourceResponse.setResponseMimeType(response!.getContentType()) + webResourceResponse.setResponseEncoding(response!.getContentEncoding()) + webResourceResponse.setResponseCode(response!.getStatusCode()) + webResourceResponse.setReasonMessage(response!.getReasonPhrase()) + webResourceResponse.setResponseData(response!.getData()) + webResourceResponse.setResponseIsReady(true); + } else { + webResourceResponse.setResponseIsReady(false) + } + }) } catch (e) { - Log.e(TAG, "handle error", e); - return null; - } - if (response != null) { - let webResourceResponse = new WebResourceResponse() - webResourceResponse.setResponseMimeType(response!.getContentType()) - webResourceResponse.setResponseEncoding(response!.getContentEncoding()) - webResourceResponse.setResponseCode(response!.getStatusCode()) - webResourceResponse.setReasonMessage(response!.getReasonPhrase()) - webResourceResponse.setResponseData(response!.getData()) - return webResourceResponse; + webResourceResponse.setResponseIsReady(false) } } - return null; + return webResourceResponse; } dispose(): void { @@ -150,7 +152,9 @@ class PathHandlerExtChannelDelegate extends ChannelDelegateImpl { handle(path: string, callback: HandleCallback): void { let channel = this.getChannel(); - if (channel == null) return; + if (channel == null) { + return; + } let obj: Map = new Map(); obj.set("path", path); channel.invokeMethod("handle", obj, callback); @@ -158,7 +162,9 @@ class PathHandlerExtChannelDelegate extends ChannelDelegateImpl { async handleSync(path: string) { let channel = this.getChannel(); - if (channel == null) return null; + if (channel == null) { + return null; + } let callback = new SyncHandleCallback(); let obj: Map = new Map(); obj.set("path", path); 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 15884771..23334793 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 @@ -66,7 +66,6 @@ export class FlutterWebView extends PlatformWebView { // set MATCH_PARENT layout params to the WebView, otherwise it won't take all the available space! //TODO - // this.webView.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); let pullToRefreshSettings: PullToRefreshSettings = new PullToRefreshSettings(); pullToRefreshSettings.parse(pullToRefreshInitialSettings); this.pullToRefreshLayout = new PullToRefreshLayout(plugin, id, pullToRefreshSettings); 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 098e896a..7dc4fa16 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 @@ -64,6 +64,7 @@ import common from '@ohos.app.ability.common'; import { FindInteractionController } from '../../find_interaction/FindInteractionController'; import { InAppWebViewClient } from './InAppWebViewClient'; import { InAppWebViewClientCompat } from './InAppWebViewClientCompat'; +import PullToRefreshLayout from '../../pull_to_refresh/PullToRefreshLayout'; const TAG = "InAppWebView" const METHOD_CHANNEL_NAME_PREFIX = "com.pichillilorenzo/flutter_inappwebview_"; @@ -108,6 +109,7 @@ export default class InAppWebView implements InAppWebViewInterface { public controller: web_webview.WebviewController = new web_webview.WebviewController(); private ohosWebViewModel: DVModel | null = null; private controllerAttached: boolean = false; + private pullToRefreshLayout: PullToRefreshLayout | null = null; constructor(context: Context, plugin: InAppWebViewFlutterPlugin, id: number, windowId: number | null | undefined, customSettings: InAppWebViewSettings, userScripts: Array, contextMenu?: Map) { @@ -125,6 +127,14 @@ export default class InAppWebView implements InAppWebViewInterface { // } } + setPullToRefreshLayout(pullToRefreshLayout: PullToRefreshLayout) { + this.pullToRefreshLayout = pullToRefreshLayout; + } + + getPullToRefreshLayout(): PullToRefreshLayout { + return this.pullToRefreshLayout!!; + } + public async createWebClient(inAppBrowserDelegate: InAppBrowserDelegate): Promise { // TODO 应返回 Promise let bundleFlags = bundleManager.BundleFlag.GET_BUNDLE_INFO_DEFAULT; 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 77504304..7b3d18f8 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 @@ -73,7 +73,8 @@ export default class InAppWebViewChromeClient { onAlert = (event: Any) => { Log.d(TAG, "onAlert=" + JSON.stringify(event)) if (this.inAppWebView != null && this.inAppWebView.channelDelegate != null) { - this.inAppWebView.channelDelegate.onJsAlert(event.url, event.message, null, new InnerJsAlertCallback(event.result, event.message)); + this.inAppWebView.channelDelegate.onJsAlert(event.url, event.message, null, + new InnerJsAlertCallback(event.result, event.message)); return true; } return false; @@ -81,7 +82,8 @@ export default class InAppWebViewChromeClient { onBeforeUnload = (event: Any) => { Log.d(TAG, "onBeforeUnload=" + JSON.stringify(event)) if (this.inAppWebView != null && this.inAppWebView.channelDelegate != null) { - this.inAppWebView.channelDelegate.onJsBeforeUnload(event.url, event.message, new InnerJsBeforeUnloadCallback(event.result, event.message)); + this.inAppWebView.channelDelegate.onJsBeforeUnload(event.url, event.message, + new InnerJsBeforeUnloadCallback(event.result, event.message)); return true; } return false; @@ -89,7 +91,8 @@ export default class InAppWebViewChromeClient { onConfirm = (event: Any) => { Log.d(TAG, "onConfirm=" + JSON.stringify(event)) if (this.inAppWebView != null && this.inAppWebView.channelDelegate != null) { - this.inAppWebView.channelDelegate.onJsConfirm(event.url, event.message, null, new InnerJsConfirmCallback(event.result, event.message)); + this.inAppWebView.channelDelegate.onJsConfirm(event.url, event.message, null, + new InnerJsConfirmCallback(event.result, event.message)); return true; } return false; @@ -98,10 +101,10 @@ export default class InAppWebViewChromeClient { 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)); - // return true; - // } + 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)); + return true; + } return false; } onConsole = (event: Any) => { @@ -247,7 +250,8 @@ export default class InAppWebViewChromeClient { let pickerProfile: cameraPicker.PickerProfile = { cameraPosition: camera.CameraPosition.CAMERA_POSITION_BACK }; - cameraPicker.pick(this.inAppWebView.context, images ? [cameraPicker.PickerMediaType.PHOTO] : [cameraPicker.PickerMediaType.VIDEO], pickerProfile) + cameraPicker.pick(this.inAppWebView.context, + images ? [cameraPicker.PickerMediaType.PHOTO] : [cameraPicker.PickerMediaType.VIDEO], pickerProfile) .then(result => { event.result.handleFileList([result.resultUri]); }).catch((err: BusinessError) => { @@ -285,7 +289,8 @@ export default class InAppWebViewChromeClient { let photoPicker = new picker.PhotoViewPicker(); photoPicker.select(photoSelectOptions).then((photoSelectResult: picker.PhotoSelectResult) => { event.result.handleFileList(photoSelectResult.photoUris); - Log.d(TAG, 'PhotoViewPicker.select successfully, photoSelectResult uri: ' + JSON.stringify(photoSelectResult)); + Log.d(TAG, + 'PhotoViewPicker.select successfully, photoSelectResult uri: ' + JSON.stringify(photoSelectResult)); }).catch((err: BusinessError) => { event.result.handleFileList([]); Log.e(TAG, 'PhotoViewPicker.select failed with err: ' + JSON.stringify(err)); @@ -300,7 +305,8 @@ export default class InAppWebViewChromeClient { documentSelectOptions.maxSelectNumber = allowMultiple ? 100000 : 1 documentSelectOptions.fileSuffixFilters = acceptTypes; documentPicker.select(documentSelectOptions).then((documentSelectResult) => { - Log.d(TAG, 'documentViewPicker.select to file succeed and uri is:' + JSON.stringify(documentSelectResult)); + Log.d(TAG, + 'documentViewPicker.select to file succeed and uri is:' + JSON.stringify(documentSelectResult)); event.result.handleFileList(documentSelectResult); }).catch((err: BusinessError) => { event.result.handleFileList([]); @@ -315,7 +321,8 @@ export default class InAppWebViewChromeClient { let audioPicker = new picker.AudioViewPicker(); audioPicker.select(audioSelectOptions).then((audioSelectResult: Array) => { event.result.handleFileList(audioSelectResult); - Log.d(TAG, 'AudioViewPicker.select successfully, audioSelectResult uri: ' + JSON.stringify(audioSelectResult)); + Log.d(TAG, + 'AudioViewPicker.select successfully, audioSelectResult uri: ' + JSON.stringify(audioSelectResult)); }).catch((err: BusinessError) => { Log.d(TAG, 'AudioViewPicker.select failed with err: ' + JSON.stringify(err)); event.result.handleFileList([]); @@ -338,13 +345,13 @@ export default class InAppWebViewChromeClient { this.inAppWebView.channelDelegate.onZoomScaleChanged(event.oldScale, event.newScale); } } - onInterceptRequest = async (event: Any) => { //对应安卓shouldInterceptRequest + onInterceptRequest = (event: Any) => { //对应安卓shouldInterceptRequest let request = WebResourceRequestExt.fromWebResourceRequest(event.request); Log.d(TAG, "onInterceptRequest=" + JSON.stringify(event)) if (this.inAppWebView.webViewAssetLoaderExt != null && this.inAppWebView.webViewAssetLoaderExt.loader != null) { try { let url = new uri.URI(request.getUrl()); - let webResourceResponse = await this.inAppWebView.webViewAssetLoaderExt.loader.shouldInterceptRequest(url); + let webResourceResponse = this.inAppWebView.webViewAssetLoaderExt.loader.shouldInterceptRequest(url); if (webResourceResponse != null) { return webResourceResponse; } @@ -353,24 +360,27 @@ export default class InAppWebViewChromeClient { } } if (this.inAppWebView.customSettings.useShouldInterceptRequest) { - let response: WebResourceResponseExt | null = null; if (this.inAppWebView.channelDelegate != null) { + let webResourceResponse = new WebResourceResponse(); try { - response = await this.inAppWebView.channelDelegate.shouldInterceptRequest(request); + this.inAppWebView.channelDelegate.shouldInterceptRequest(request).then(response => { + if (response != null) { + webResourceResponse.setResponseData(response.getData()) + webResourceResponse.setResponseMimeType(response.getContentType()) + webResourceResponse.setResponseEncoding(response.getContentEncoding()) + webResourceResponse.setResponseCode(response.getStatusCode()) + webResourceResponse.setReasonMessage(response.getReasonPhrase()) + webResourceResponse.setResponseHeader(response.getHeaderArray()) + webResourceResponse.setResponseIsReady(true) + } else { + webResourceResponse.setResponseIsReady(false); + } + }) } catch (e) { Log.e(TAG, "", e); - return null; + webResourceResponse.setResponseIsReady(false); } - } - if (response != null) { - let webResourceResponse = new WebResourceResponse(); - webResourceResponse.setResponseData(response.getData()) - webResourceResponse.setResponseMimeType(response.getContentType()) - webResourceResponse.setResponseEncoding(response.getContentEncoding()) - webResourceResponse.setResponseCode(response.getStatusCode()) - webResourceResponse.setReasonMessage(response.getReasonPhrase()) - webResourceResponse.setResponseHeader(response.getHeaderArray()) - return new WebResourceResponse(); + return webResourceResponse; } return null; } @@ -383,30 +393,40 @@ export default class InAppWebViewChromeClient { } - if (this.inAppWebView.customSettings.resourceCustomSchemes != null && this.inAppWebView.customSettings.resourceCustomSchemes.indexOf(scheme) > -1) { - let customSchemeResponse: CustomSchemeResponse | null = null; + if (this.inAppWebView.customSettings.resourceCustomSchemes != null && + this.inAppWebView.customSettings.resourceCustomSchemes.indexOf(scheme) > -1) { if (this.inAppWebView.channelDelegate != null) { + let resourceResponse = new WebResourceResponse(); try { - customSchemeResponse = await this.inAppWebView.channelDelegate.onLoadResourceWithCustomScheme(request); - } catch (e) { - Log.e(TAG, "", e); - return null; - } - } - - if (customSchemeResponse != null) { - let response: WebResourceResponse | null = null; - try { - response = this.inAppWebView.contentBlockerHandler.checkUrl(this.inAppWebView, request, customSchemeResponse.getContentType()); + this.inAppWebView.channelDelegate.onLoadResourceWithCustomScheme(request).then(customSchemeResponse => { + if (customSchemeResponse != null) { + try { + response = this.inAppWebView.contentBlockerHandler.checkUrl(this.inAppWebView, request, + customSchemeResponse.getContentType()); + } catch (e) { + Log.e(TAG, "", e); + } + if (response != null) { + resourceResponse.setResponseData(response.getResponseData()) + resourceResponse.setResponseMimeType(response.getResponseMimeType()) + resourceResponse.setResponseEncoding(response.getResponseEncoding()) + resourceResponse.setResponseCode(response.getResponseCode()) + resourceResponse.setReasonMessage(response.getReasonMessage()) + resourceResponse.setResponseHeader(response.getResponseHeader()) + resourceResponse.setResponseIsReady(true) + } else { + resourceResponse.setResponseMimeType(customSchemeResponse.getContentType()); + resourceResponse.setResponseEncoding(customSchemeResponse.getContentEncoding()); + resourceResponse.setResponseData(customSchemeResponse.getData()) + } + } else { + resourceResponse.setResponseIsReady(false) + } + }); } catch (e) { Log.e(TAG, "", e); + resourceResponse.setResponseIsReady(false) } - if (response != null) - return response; - let resourceResponse = new WebResourceResponse(); - resourceResponse.setResponseMimeType(customSchemeResponse.getContentType()); - resourceResponse.setResponseEncoding(customSchemeResponse.getContentEncoding()); - resourceResponse.setResponseData(customSchemeResponse.getData()) return resourceResponse; } } @@ -437,7 +457,8 @@ export default class InAppWebViewChromeClient { } onPermissionRequest = (event: Any) => { if (this.inAppWebView != null && this.inAppWebView.channelDelegate != null) { - this.inAppWebView.channelDelegate.onPermissionRequest(event.request.getOrigin(), event.request.getAccessibleResource(), null, + this.inAppWebView.channelDelegate.onPermissionRequest(event.request.getOrigin(), + event.request.getAccessibleResource(), null, new InnerPermissionRequestCallback(event.request)); } else { event.request.deny(); @@ -449,24 +470,28 @@ export default class InAppWebViewChromeClient { Log.d(TAG, "onContextMenuShow=" + JSON.stringify(event)) return false; } - onContextMenuHide = (callback: OnContextMenuHideCallback) => { + onContextMenuHide = () => { // TODO Log.d(TAG, "onContextMenuHide=") } onScroll = (event: Any) => { Log.d(TAG, "onScroll=" + JSON.stringify(event)) - if (this.inAppWebView.channelDelegate != null) this.inAppWebView.channelDelegate.onScrollChanged(event.xOffset, event.yOffset); + if (this.inAppWebView.channelDelegate != null) { + this.inAppWebView.channelDelegate.onScrollChanged(event.xOffset, + event.yOffset); + } } onGeolocationShow = (event: Any) => { Log.d(TAG, "onGeolocationShow=" + JSON.stringify(event)) if (this.inAppWebView != null && this.inAppWebView.channelDelegate != null) { - this.inAppWebView.channelDelegate.onGeolocationPermissionsShowPrompt(event.origin, new InnerGeolocationPermissionsShowPromptCallback(event.origin, event.geolocation)); + this.inAppWebView.channelDelegate.onGeolocationPermissionsShowPrompt(event.origin, + new InnerGeolocationPermissionsShowPromptCallback(event.origin, event.geolocation)); } else { event.geolocation.invoke(event.origin, false, false); } } - onGeolocationHide = (event: Any) => { - Log.d(TAG, "onGeolocationHide=" + JSON.stringify(event)) + onGeolocationHide = () => { + Log.d(TAG, "onGeolocationHide=") if (this.inAppWebView != null && this.inAppWebView.channelDelegate != null) { this.inAppWebView.channelDelegate.onGeolocationPermissionsHidePrompt(); } @@ -480,8 +505,8 @@ export default class InAppWebViewChromeClient { } this.inAppWebView.setInFullscreen(true); } - onFullScreenExit = (event: Any) => { - Log.d(TAG, "onFullScreenExit=" + JSON.stringify(event)) + onFullScreenExit = () => { + Log.d(TAG, "onFullScreenExit=") // TODO 设置Ability退出全屏 if (this.fullScreenExitHandler) { this.fullScreenExitHandler.exitFullScreen() @@ -494,8 +519,8 @@ export default class InAppWebViewChromeClient { onWindowNew = (event: Any) => { Log.d(TAG, "onWindowNew=" + JSON.stringify(event)) } - onWindowExit = (event: Any) => { - Log.d(TAG, "onWindowExit=" + JSON.stringify(event)) + onWindowExit = () => { + Log.d(TAG, "onWindowExit=") } onSearchResultReceive = (event: Any) => { Log.d(TAG, "onSearchResultReceive=" + JSON.stringify(event)) @@ -536,24 +561,25 @@ export default class InAppWebViewChromeClient { onFirstContentfulPaint = (event: Any) => { Log.d(TAG, "onFirstContentfulPaint=" + JSON.stringify(event)) } - onLoadIntercept = async (event: Any) => { //对应安卓 shouldOverrideUrlLoading + onLoadIntercept = (event: Any) => { //对应安卓 shouldOverrideUrlLoading OHOS不知道异步 不知道如何适配了 + // TODO Log.d(TAG, "onLoadIntercept=" + event.data.getRequestUrl()) - if (this.inAppWebView.customSettings.useShouldOverrideUrlLoading) { - let request = WebResourceRequestExt.fromWebResourceRequest(event.data); - return await this.onShouldOverrideUrlLoading( - this.inAppWebView, - request.getUrl(), - request.getMethod(), - request.getHeaders(), - request.getForMainFrame(), - request.isHasGesture(), - request.getRedirect()); - } + // if (this.inAppWebView.customSettings.useShouldOverrideUrlLoading) { + // let request = WebResourceRequestExt.fromWebResourceRequest(event.data); + // return await this.onShouldOverrideUrlLoading( + // this.inAppWebView, + // request.getUrl(), + // request.getMethod(), + // request.getHeaders(), + // request.getForMainFrame(), + // request.isHasGesture(), + // request.getRedirect()); + // } Log.d(TAG, "onLoadInterceptEnd=" + event.data.getRequestUrl()) return false; } - onRequestSelected = (event: Any) => { - Log.d(TAG, "onRequestSelected=" + JSON.stringify(event)) + onRequestSelected = () => { + Log.d(TAG, "onRequestSelected=") } onScreenCaptureRequest = (event: Any) => { Log.d(TAG, "onScreenCaptureRequest=" + JSON.stringify(event)) @@ -561,10 +587,10 @@ export default class InAppWebViewChromeClient { onOverScroll = (event: Any) => { Log.d(TAG, "onOverScroll=" + JSON.stringify(event)) } - onNavigationEntryCommitted = (callback: OnNavigationEntryCommittedCallback) => { + onNavigationEntryCommitted = () => { Log.d(TAG, "onNavigationEntryCommitted=") } - onSafeBrowsingCheckResult = (callback: OnSafeBrowsingCheckResultCallback) => { + onSafeBrowsingCheckResult = () => { Log.d(TAG, "onSafeBrowsingCheckResult=") } onNativeEmbedLifecycleChange = (callback: NativeEmbedDataInfo) => { @@ -574,8 +600,9 @@ export default class InAppWebViewChromeClient { Log.d(TAG, "onNativeEmbedGestureEvent=") } - private async onShouldOverrideUrlLoading(webView: InAppWebView, url: string, method: string, headers: Map, - isForMainFrame: boolean, hasGesture: boolean, isRedirect: boolean) { + private async onShouldOverrideUrlLoading(webView: InAppWebView, url: string, method: string, + headers: Map, + isForMainFrame: boolean, hasGesture: boolean, isRedirect: boolean) { let request = new URLRequest(url, method, null, headers); let navigationAction = new NavigationAction(request, isForMainFrame, hasGesture, isRedirect); @@ -702,7 +729,8 @@ class InnerJsAlertCallback extends JsAlertCallback { this.result.handleCancel(); } - private createAlertDialog(message: string, result: JsResult, responseMessage: string | null, confirmButtonTitle: string | null) { + private createAlertDialog(message: string, result: JsResult, responseMessage: string | null, + confirmButtonTitle: string | null) { let alertMessage = (responseMessage != null && responseMessage.length > 0) ? responseMessage : message; AlertDialog.show( { @@ -768,7 +796,7 @@ class InnerJsConfirmCallback extends JsConfirmCallback { } private createConfirmDialog(message: string, result: JsResult, responseMessage: string | null, - confirmButtonTitle: string | null, cancelButtonTitle: string | null) { + confirmButtonTitle: string | null, cancelButtonTitle: string | null) { let alertMessage = (responseMessage != null && responseMessage.length > 0) ? responseMessage : message; AlertDialog.show( { @@ -840,7 +868,8 @@ class InnerJsPromptCallback extends JsPromptCallback { confirmButtonTitle = response.getConfirmButtonTitle(); cancelButtonTitle = response.getCancelButtonTitle(); } - this.createPromptDialog(this.message, this.defaultValue, this.result, responseMessage, responseDefaultValue, value, cancelButtonTitle, confirmButtonTitle); + this.createPromptDialog(this.message, this.defaultValue, this.result, responseMessage, responseDefaultValue, value, + cancelButtonTitle, confirmButtonTitle); } error(errorCode: string, errorMessage: string, errorDetails: Any): void { @@ -849,22 +878,31 @@ class InnerJsPromptCallback extends JsPromptCallback { } private createPromptDialog(message: string, defaultValue: string, result: JsResult, responseMessage: string | null, - responseDefaultValue: string | null, value: string | null, cancelButtonTitle: string | null, - confirmButtonTitle: string | null) { - let initValue = (responseDefaultValue != null && responseDefaultValue.length > 0) ? responseDefaultValue : defaultValue; + responseDefaultValue: string | null, value: string | null, cancelButtonTitle: string | null, + confirmButtonTitle: string | null) { + let initValue = + (responseDefaultValue != null && responseDefaultValue.length > 0) ? responseDefaultValue : defaultValue; let alertMessage = (responseMessage != null && responseMessage.length > 0) ? responseMessage : message; let finalValue = value; let customDialogId = -1; - //TODO 这里存在一个缺陷,就是点击空白弹窗消失没办法监听所以没办法调用到cancel方法会知道存在bug 需要再API12才可支持 需要后续完善 + let isCancel = true; promptAction.openCustomDialog({ - builder: ohosPromptDialogBuilder.bind(this.uiObject, initValue, alertMessage, cancelButtonTitle, confirmButtonTitle, () => { - result.handleCancel() - promptAction.closeCustomDialog(customDialogId) - }, (value: string | null) => { - promptAction.closeCustomDialog(customDialogId) - result.handlePromptConfirm(finalValue != null ? finalValue : value); - }), - alignment: DialogAlignment.Center + builder: ohosPromptDialogBuilder.bind(this.uiObject, initValue, alertMessage, cancelButtonTitle, + confirmButtonTitle, () => { + isCancel = false + result.handleCancel() + promptAction.closeCustomDialog(customDialogId) + }, (value: string | null) => { + isCancel = false + promptAction.closeCustomDialog(customDialogId) + result.handlePromptConfirm(finalValue != null ? finalValue : value); + }), + alignment: DialogAlignment.Center, + onDidDisappear: () => { + if(isCancel){ + result.handleCancel() + } + } }).then((dialogId: number) => { customDialogId = dialogId }) @@ -916,7 +954,7 @@ class InnerJsBeforeUnloadCallback extends JsBeforeUnloadCallback { } private createBeforeUnloadDialog(message: string, result: JsResult, responseMessage: string | null, - confirmButtonTitle: string | null, cancelButtonTitle: string | null) { + confirmButtonTitle: string | null, cancelButtonTitle: string | null) { let alertMessage = (responseMessage != null && responseMessage.length > 0) ? responseMessage : message; AlertDialog.show( { @@ -1001,4 +1039,4 @@ class InnerGeolocationPermissionsShowPromptCallback extends GeolocationPermissio Log.e(TAG, errorCode + ", " + ((errorMessage != null) ? errorMessage : "")); this.defaultBehaviour(null); } -} +} \ No newline at end of file diff --git a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/webview/in_app_webview/OhosWebView.ets b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/webview/in_app_webview/OhosWebView.ets index b2b7f45a..fc76d741 100644 --- a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/webview/in_app_webview/OhosWebView.ets +++ b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/webview/in_app_webview/OhosWebView.ets @@ -14,117 +14,156 @@ */ import web_webview from '@ohos.web.webview' +import common from '@ohos.app.ability.common'; +import { Any } from '@ohos/flutter_ohos' import { Params } from '@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformView' import { FlutterWebView } from './FlutterWebView' import InAppWebView from './InAppWebView' +import EventConstant from '../../EventConstant' @Component export struct OhosWebView { @Prop params: Params; controller: web_webview.WebviewController = new web_webview.WebviewController() inAppWebView: InAppWebView | null = null + @State isRefreshing: boolean = false + @State isEnableRefresh: boolean = false aboutToAppear(): void { + this.isEnableRefresh = this.inAppWebView!.getPullToRefreshLayout().settings.enabled; + let context = getContext() as common.UIAbilityContext; + context.eventHub.on(EventConstant.EVENT_PULL_SETREFRESHING, (refreshing : boolean) => { + this.isRefreshing = refreshing; + }); + } + aboutToDisappear(): void { + let context = getContext() as common.UIAbilityContext; + context.eventHub.off(EventConstant.EVENT_PULL_SETREFRESHING); } build() { Column() { - Web( - { - src: "", - controller: this.controller + if (this.isEnableRefresh) { + Refresh({ refreshing: $$this.isRefreshing }) { + this.buildWeb() + } + .onStateChange((refreshStatus: RefreshStatus) => { + console.info('Refresh onStatueChange state is ' + refreshStatus) }) - .onControllerAttached(this.inAppWebView!.onControllerAttached) - .onAlert(this.inAppWebView!.inAppWebViewChromeClient?.onAlert) - .onBeforeUnload(this.inAppWebView!.inAppWebViewChromeClient?.onBeforeUnload) - .onConfirm(this.inAppWebView!.inAppWebViewChromeClient?.onConfirm) - .onPrompt((event) => { - return this.inAppWebView!.inAppWebViewChromeClient?.onPrompt(event, this) + .onRefreshing(() => { + this.inAppWebView!.getPullToRefreshLayout().onRefresh() }) - .onConsole(this.inAppWebView!.inAppWebViewChromeClient?.onConsole) - .onDownloadStart(this.inAppWebView!.inAppWebViewChromeClient?.onDownloadStart) - .onErrorReceive(this.inAppWebView!.inAppWebViewChromeClient?.onErrorReceive) - .onHttpErrorReceive(this.inAppWebView!.inAppWebViewChromeClient?.onHttpErrorReceive) - .onPageBegin(this.inAppWebView!.inAppWebViewChromeClient?.onPageBegin) - .onPageEnd(this.inAppWebView!.inAppWebViewChromeClient?.onPageEnd) - .onProgressChange(this.inAppWebView!.inAppWebViewChromeClient?.onProgressChange) - .onTitleReceive(this.inAppWebView!.inAppWebViewChromeClient?.onTitleReceive) - .onRefreshAccessedHistory(this.inAppWebView!.inAppWebViewChromeClient?.onRefreshAccessedHistory) - .onRenderExited(this.inAppWebView!.inAppWebViewChromeClient?.onRenderExited) - .onShowFileSelector(this.inAppWebView!.inAppWebViewChromeClient?.onShowFileSelector) - .onResourceLoad(this.inAppWebView!.inAppWebViewChromeClient?.onResourceLoad) - .onScaleChange(this.inAppWebView!.inAppWebViewChromeClient?.onScaleChange) - // .onInterceptRequest(this.inAppWebView!.inAppWebViewChromeClient?.onInterceptRequest) - .onHttpAuthRequest(this.inAppWebView!.inAppWebViewChromeClient?.onHttpAuthRequest) - .onSslErrorEventReceive(this.inAppWebView!.inAppWebViewChromeClient?.onSslErrorEventReceive) - .onClientAuthenticationRequest(this.inAppWebView!.inAppWebViewChromeClient?.onClientAuthenticationRequest) - .onPermissionRequest(this.inAppWebView!.inAppWebViewChromeClient?.onPermissionRequest) - .onContextMenuShow(this.inAppWebView!.inAppWebViewChromeClient?.onContextMenuShow) - // .onContextMenuHide(this.inAppWebView!.inAppWebViewChromeClient?.onContextMenuHide) - .onScroll(this.inAppWebView!.inAppWebViewChromeClient?.onScroll) - .onGeolocationShow(this.inAppWebView!.inAppWebViewChromeClient?.onGeolocationShow) - // .onGeolocationHide(this.inAppWebView!.inAppWebViewChromeClient?.onGeolocationHide) - .onFullScreenEnter(this.inAppWebView!.inAppWebViewChromeClient?.onFullScreenEnter) - // .onFullScreenExit(this.inAppWebView!.inAppWebViewChromeClient?.onFullScreenExit) - .onWindowNew(this.inAppWebView!.inAppWebViewChromeClient?.onWindowNew) - // .onWindowExit(this.inAppWebView!.inAppWebViewChromeClient?.onWindowExit) - .onSearchResultReceive(this.inAppWebView!.inAppWebViewChromeClient?.onSearchResultReceive) - .onDataResubmitted(this.inAppWebView!.inAppWebViewChromeClient?.onDataResubmitted) - .onPageVisible(this.inAppWebView!.inAppWebViewChromeClient?.onPageVisible) - .onInterceptKeyEvent(this.inAppWebView!.inAppWebViewChromeClient?.onInterceptKeyEvent) - .onTouchIconUrlReceived(this.inAppWebView!.inAppWebViewChromeClient?.onTouchIconUrlReceived) - .onFaviconReceived(this.inAppWebView!.inAppWebViewChromeClient?.onFaviconReceived) - .onAudioStateChanged(this.inAppWebView!.inAppWebViewChromeClient?.onAudioStateChanged) - .onFirstContentfulPaint(this.inAppWebView!.inAppWebViewChromeClient?.onFirstContentfulPaint) - // .onLoadIntercept(this.inAppWebView!.inAppWebViewChromeClient?.onLoadIntercept) - // .onRequestSelected(this.inAppWebView!.inAppWebViewChromeClient?.onRequestSelected) - .onScreenCaptureRequest(this.inAppWebView!.inAppWebViewChromeClient?.onScreenCaptureRequest) - .onOverScroll(this.inAppWebView!.inAppWebViewChromeClient?.onOverScroll) - // .onNavigationEntryCommitted(this.inAppWebView!.inAppWebViewChromeClient?.onNavigationEntryCommitted) - // .onSafeBrowsingCheckResult(this.inAppWebView!.inAppWebViewChromeClient?.onSafeBrowsingCheckResult) - .onNativeEmbedLifecycleChange(this.inAppWebView!.inAppWebViewChromeClient?.onNativeEmbedLifecycleChange) - .onNativeEmbedGestureEvent(this.inAppWebView!.inAppWebViewChromeClient?.onNativeEmbedGestureEvent) - .domStorageAccess(this.inAppWebView!.customSettings.domStorageAccess) - .fileAccess(this.inAppWebView!.customSettings.fileAccess) - .imageAccess(this.inAppWebView!.customSettings.imageAccess) - .javaScriptAccess(this.inAppWebView!.customSettings.javaScriptAccess) - .overScrollMode(this.inAppWebView!.customSettings.overScrollMode) - .mixedMode(this.inAppWebView!.customSettings.mixedMode) - .onlineImageAccess(this.inAppWebView!.customSettings.onlineImageAccess) - .zoomAccess(this.inAppWebView!.customSettings.zoomAccess) - .overviewModeAccess(this.inAppWebView!.customSettings.overviewModeAccess) - .databaseAccess(this.inAppWebView!.customSettings.databaseAccess) - .geolocationAccess(this.inAppWebView!.customSettings.geolocationAccess) - .mediaPlayGestureAccess(this.inAppWebView!.customSettings.mediaPlayGestureAccess) - .multiWindowAccess(this.inAppWebView!.customSettings.multiWindowAccess) - .horizontalScrollBarAccess(this.inAppWebView!.customSettings.horizontalScrollBarAccess) - .verticalScrollBarAccess(this.inAppWebView!.customSettings.verticalScrollBarAccess) - .cacheMode(this.inAppWebView!.customSettings.cacheMode) - .textZoomRatio(this.inAppWebView!.customSettings.textZoomRatio) - .initialScale(this.inAppWebView!.customSettings.initialScale) - .blockNetwork(this.inAppWebView!.customSettings.blockNetwork) - .defaultFixedFontSize(this.inAppWebView!.customSettings.defaultFixedFontSize) - .defaultFontSize(this.inAppWebView!.customSettings.defaultFontSize) - .minFontSize(this.inAppWebView!.customSettings.minFontSize) - .minLogicalFontSize(this.inAppWebView!.customSettings.minLogicalFontSize) - .webFixedFont(this.inAppWebView!.customSettings.webFixedFont) - .webSansSerifFont(this.inAppWebView!.customSettings.webSansSerifFont) - .webSerifFont(this.inAppWebView!.customSettings.webSerifFont) - .webStandardFont(this.inAppWebView!.customSettings.webStandardFont) - .webFantasyFont(this.inAppWebView!.customSettings.webFantasyFont) - .webCursiveFont(this.inAppWebView!.customSettings.webCursiveFont) - .darkMode(this.inAppWebView!.customSettings.darkMode) - .forceDarkAccess(this.inAppWebView!.customSettings.forceDarkAccess) - .pinchSmooth(this.inAppWebView!.customSettings.pinchSmooth) - .allowWindowOpenMethod(this.inAppWebView!.customSettings.allowWindowOpenMethod) - .layoutMode(this.inAppWebView!.customSettings.layoutMode) - .enableNativeEmbedMode(this.inAppWebView!.customSettings.enableNativeEmbedMode) + } else { + this.buildWeb() + } } } + + @Builder + buildWeb() { + Web( + { + src: "", + controller: this.controller + }) + .onControllerAttached(this.inAppWebView!.onControllerAttached) + .onAlert(this.inAppWebView!.inAppWebViewChromeClient?.onAlert) + .onBeforeUnload(this.inAppWebView!.inAppWebViewChromeClient?.onBeforeUnload) + .onConfirm(this.inAppWebView!.inAppWebViewChromeClient?.onConfirm) + .onPrompt((event) => { + return this.inAppWebView!.inAppWebViewChromeClient?.onPrompt(event, this) + }) + .onConsole(this.inAppWebView!.inAppWebViewChromeClient?.onConsole) + .onDownloadStart(this.inAppWebView!.inAppWebViewChromeClient?.onDownloadStart) + .onErrorReceive(this.inAppWebView!.inAppWebViewChromeClient?.onErrorReceive) + .onHttpErrorReceive(this.inAppWebView!.inAppWebViewChromeClient?.onHttpErrorReceive) + .onPageBegin(this.inAppWebView!.inAppWebViewChromeClient?.onPageBegin) + .onPageEnd(this.inAppWebView!.inAppWebViewChromeClient?.onPageEnd) + .onProgressChange(this.inAppWebView!.inAppWebViewChromeClient?.onProgressChange) + .onTitleReceive(this.inAppWebView!.inAppWebViewChromeClient?.onTitleReceive) + .onRefreshAccessedHistory(this.inAppWebView!.inAppWebViewChromeClient?.onRefreshAccessedHistory) + .onRenderExited(this.inAppWebView!.inAppWebViewChromeClient?.onRenderExited) + .onShowFileSelector(this.inAppWebView!.inAppWebViewChromeClient?.onShowFileSelector) + .onResourceLoad(this.inAppWebView!.inAppWebViewChromeClient?.onResourceLoad) + .onScaleChange(this.inAppWebView!.inAppWebViewChromeClient?.onScaleChange) + .onInterceptRequest((event) => { + return this.inAppWebView!.inAppWebViewChromeClient?.onInterceptRequest(event) + }) + .onHttpAuthRequest(this.inAppWebView!.inAppWebViewChromeClient?.onHttpAuthRequest) + .onSslErrorEventReceive(this.inAppWebView!.inAppWebViewChromeClient?.onSslErrorEventReceive) + .onClientAuthenticationRequest(this.inAppWebView!.inAppWebViewChromeClient?.onClientAuthenticationRequest) + .onPermissionRequest(this.inAppWebView!.inAppWebViewChromeClient?.onPermissionRequest) + .onContextMenuShow(this.inAppWebView!.inAppWebViewChromeClient?.onContextMenuShow) + .onContextMenuHide(this.inAppWebView!.inAppWebViewChromeClient?.onContextMenuHide) + .onScroll(this.inAppWebView!.inAppWebViewChromeClient?.onScroll) + .onGeolocationShow(this.inAppWebView!.inAppWebViewChromeClient?.onGeolocationShow) + .onGeolocationHide(this.inAppWebView!.inAppWebViewChromeClient?.onGeolocationHide) + .onFullScreenEnter(this.inAppWebView!.inAppWebViewChromeClient?.onFullScreenEnter) + .onFullScreenExit(this.inAppWebView!.inAppWebViewChromeClient?.onFullScreenExit) + .onWindowNew(this.inAppWebView!.inAppWebViewChromeClient?.onWindowNew) + .onWindowExit(this.inAppWebView!.inAppWebViewChromeClient?.onWindowExit) + .onSearchResultReceive(this.inAppWebView!.inAppWebViewChromeClient?.onSearchResultReceive) + .onDataResubmitted(this.inAppWebView!.inAppWebViewChromeClient?.onDataResubmitted) + .onPageVisible(this.inAppWebView!.inAppWebViewChromeClient?.onPageVisible) + .onInterceptKeyEvent(this.inAppWebView!.inAppWebViewChromeClient?.onInterceptKeyEvent) + .onTouchIconUrlReceived(this.inAppWebView!.inAppWebViewChromeClient?.onTouchIconUrlReceived) + .onFaviconReceived(this.inAppWebView!.inAppWebViewChromeClient?.onFaviconReceived) + .onAudioStateChanged(this.inAppWebView!.inAppWebViewChromeClient?.onAudioStateChanged) + .onFirstContentfulPaint(this.inAppWebView!.inAppWebViewChromeClient?.onFirstContentfulPaint) + .onLoadIntercept((event) => { + return this.inAppWebView!.inAppWebViewChromeClient?.onLoadIntercept(event) + }) + .onRequestSelected(this.inAppWebView!.inAppWebViewChromeClient?.onRequestSelected) + .onScreenCaptureRequest(this.inAppWebView!.inAppWebViewChromeClient?.onScreenCaptureRequest) + .onOverScroll(this.inAppWebView!.inAppWebViewChromeClient?.onOverScroll) + .onNavigationEntryCommitted(this.inAppWebView!.inAppWebViewChromeClient?.onNavigationEntryCommitted) + .onSafeBrowsingCheckResult(this.inAppWebView!.inAppWebViewChromeClient?.onSafeBrowsingCheckResult) + .onNativeEmbedLifecycleChange(this.inAppWebView!.inAppWebViewChromeClient?.onNativeEmbedLifecycleChange) + .onNativeEmbedGestureEvent(this.inAppWebView!.inAppWebViewChromeClient?.onNativeEmbedGestureEvent) + .domStorageAccess(this.inAppWebView!.customSettings.domStorageAccess) + .fileAccess(this.inAppWebView!.customSettings.fileAccess) + .imageAccess(this.inAppWebView!.customSettings.imageAccess) + .javaScriptAccess(this.inAppWebView!.customSettings.javaScriptAccess) + .overScrollMode(this.inAppWebView!.customSettings.overScrollMode) + .mixedMode(this.inAppWebView!.customSettings.mixedMode) + .onlineImageAccess(this.inAppWebView!.customSettings.onlineImageAccess) + .zoomAccess(this.inAppWebView!.customSettings.zoomAccess) + .overviewModeAccess(this.inAppWebView!.customSettings.overviewModeAccess) + .databaseAccess(this.inAppWebView!.customSettings.databaseAccess) + .geolocationAccess(this.inAppWebView!.customSettings.geolocationAccess) + .mediaPlayGestureAccess(this.inAppWebView!.customSettings.mediaPlayGestureAccess) + .multiWindowAccess(this.inAppWebView!.customSettings.multiWindowAccess) + .horizontalScrollBarAccess(this.inAppWebView!.customSettings.horizontalScrollBarAccess) + .verticalScrollBarAccess(this.inAppWebView!.customSettings.verticalScrollBarAccess) + .cacheMode(this.inAppWebView!.customSettings.cacheMode) + .textZoomRatio(this.inAppWebView!.customSettings.textZoomRatio) + .initialScale(this.inAppWebView!.customSettings.initialScale) + .blockNetwork(this.inAppWebView!.customSettings.blockNetwork) + .defaultFixedFontSize(this.inAppWebView!.customSettings.defaultFixedFontSize) + .defaultFontSize(this.inAppWebView!.customSettings.defaultFontSize) + .minFontSize(this.inAppWebView!.customSettings.minFontSize) + .minLogicalFontSize(this.inAppWebView!.customSettings.minLogicalFontSize) + .webFixedFont(this.inAppWebView!.customSettings.webFixedFont) + .webSansSerifFont(this.inAppWebView!.customSettings.webSansSerifFont) + .webSerifFont(this.inAppWebView!.customSettings.webSerifFont) + .webStandardFont(this.inAppWebView!.customSettings.webStandardFont) + .webFantasyFont(this.inAppWebView!.customSettings.webFantasyFont) + .webCursiveFont(this.inAppWebView!.customSettings.webCursiveFont) + .darkMode(this.inAppWebView!.customSettings.darkMode) + .forceDarkAccess(this.inAppWebView!.customSettings.forceDarkAccess) + .pinchSmooth(this.inAppWebView!.customSettings.pinchSmooth) + .allowWindowOpenMethod(this.inAppWebView!.customSettings.allowWindowOpenMethod) + .layoutMode(this.inAppWebView!.customSettings.layoutMode) + .enableNativeEmbedMode(this.inAppWebView!.customSettings.enableNativeEmbedMode) + } } @Builder export function buildOhosWebView(params: Params) { - OhosWebView({ params: params, controller: (params.platformView as FlutterWebView).getController(), inAppWebView: (params.platformView as FlutterWebView).getWebView() }) + OhosWebView({ + params: params, + controller: (params.platformView as FlutterWebView).getController(), + inAppWebView: (params.platformView as FlutterWebView).getWebView() + }) } \ No newline at end of file -- Gitee From 4224beb988981462bd2d4360d04fc956efc0b600 Mon Sep 17 00:00:00 2001 From: zhuzhengjun Date: Tue, 11 Jun 2024 15:40:17 +0800 Subject: [PATCH 2/4] =?UTF-8?q?=E6=94=AF=E6=8C=81canScrollVertically?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zhuzhengjun --- .../plugin/webview/InAppWebViewInterface.ets | 2 +- .../plugin/webview/WebViewChannelDelegate.ets | 6 +++++- .../webview/in_app_webview/InAppWebView.ets | 20 ++++++++++++------- .../webview/in_app_webview/OhosWebView.ets | 1 + 4 files changed, 20 insertions(+), 9 deletions(-) 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 09e18944..36f3bce9 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 @@ -83,7 +83,7 @@ export default interface InAppWebViewInterface { canScrollVertically(): boolean - canScrollHorizontally(): boolean + canScrollHorizontally(callback: ValueCallback): void getUrl(): string 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 9f30f5d0..46a66699 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 @@ -639,7 +639,11 @@ export default class WebViewChannelDelegate extends ChannelDelegateImpl { break; case WebViewChannelDelegateMethods.canScrollHorizontally: if (this.webView != null) { - result.success(this.webView.canScrollHorizontally()); + this.webView.canScrollHorizontally({ + onReceiveValue(canScroll: boolean | null): void { + result.success(canScroll); + } + }); } else { result.success(false); } 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 7dc4fa16..ea5de5fe 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 @@ -110,6 +110,8 @@ export default class InAppWebView implements InAppWebViewInterface { private ohosWebViewModel: DVModel | null = null; private controllerAttached: boolean = false; private pullToRefreshLayout: PullToRefreshLayout | null = null; + private viewWidth = 0; + private viewHeight= 0; constructor(context: Context, plugin: InAppWebViewFlutterPlugin, id: number, windowId: number | null | undefined, customSettings: InAppWebViewSettings, userScripts: Array, contextMenu?: Map) { @@ -925,6 +927,7 @@ export default class InAppWebView implements InAppWebViewInterface { } public addWebMessageListener(webMessageListener: WebMessageListener): void { + //TODO // if (WebViewFeature.isFeatureSupported(WebViewFeature.WEB_MESSAGE_LISTENER)) { // WebViewCompat.addWebMessageListener(this, webMessageListener.jsObjectName, webMessageListener.allowedOriginRules, webMessageListener.listener); // webMessageListeners.add(webMessageListener); @@ -932,15 +935,13 @@ export default class InAppWebView implements InAppWebViewInterface { } public canScrollVertically(): boolean { - /// 对比可滚动高度及当前内容高度 - // return computeVerticalScrollRange() > computeVerticalScrollExtent(); - return false; + return this.controller.getPageHeight() > this.viewHeight; } - public canScrollHorizontally(): boolean { - /// 对比可滑动宽度及当前内容宽度 - // return computeHorizontalScrollRange() > computeHorizontalScrollExtent(); - return false; + public canScrollHorizontally(callback: ValueCallback) { + this.controller.runJavaScriptExt("document.documentElement.scrollWidth;").then(result => { + callback.onReceiveValue(result.getNumber() > this.viewWidth) + }) } public isInFullscreen(): boolean { @@ -968,6 +969,11 @@ export default class InAppWebView implements InAppWebViewInterface { this.controllerAttached = true } + onAreaChange = (oldValue: Area, newValue: Area) => { + this.viewWidth = vp2px(newValue.width as number) + this.viewHeight = vp2px(newValue.height as number) + } + toWebHeaders(headers: Map): Array { let result: Array = new Array; if (headers == null || headers.size == 0) { diff --git a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/webview/in_app_webview/OhosWebView.ets b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/webview/in_app_webview/OhosWebView.ets index fc76d741..f353f549 100644 --- a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/webview/in_app_webview/OhosWebView.ets +++ b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/webview/in_app_webview/OhosWebView.ets @@ -121,6 +121,7 @@ export struct OhosWebView { .onSafeBrowsingCheckResult(this.inAppWebView!.inAppWebViewChromeClient?.onSafeBrowsingCheckResult) .onNativeEmbedLifecycleChange(this.inAppWebView!.inAppWebViewChromeClient?.onNativeEmbedLifecycleChange) .onNativeEmbedGestureEvent(this.inAppWebView!.inAppWebViewChromeClient?.onNativeEmbedGestureEvent) + .onAreaChange(this.inAppWebView!.onAreaChange) .domStorageAccess(this.inAppWebView!.customSettings.domStorageAccess) .fileAccess(this.inAppWebView!.customSettings.fileAccess) .imageAccess(this.inAppWebView!.customSettings.imageAccess) -- Gitee From 5fae1055228b8cadce0b628d7f0810ef2415e3b5 Mon Sep 17 00:00:00 2001 From: zhuzhengjun Date: Wed, 12 Jun 2024 08:39:32 +0800 Subject: [PATCH 3/4] =?UTF-8?q?=E5=AF=B9=E6=8E=A5onHttpAuthRequest?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zhuzhengjun --- .../CredentialDatabase.ets | 11 +- .../types/HttpAuthenticationChallenge.ets | 2 +- .../plugin/types/URLProtectionSpace.ets | 13 +- .../InAppWebViewChromeClient.ets | 126 +++++++++++++++++- 4 files changed, 134 insertions(+), 18 deletions(-) diff --git a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/credential_database/CredentialDatabase.ets b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/credential_database/CredentialDatabase.ets index 8894f2ef..983b6f8e 100644 --- a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/credential_database/CredentialDatabase.ets +++ b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/credential_database/CredentialDatabase.ets @@ -51,7 +51,7 @@ export default class CredentialDatabase { let credentials: List = new List(); let protectionSpace = await this.protectionSpaceDao.find(host, protocol, realm, port); if (protectionSpace != null) { - credentials = await this.credentialDao.getAllByProtectionSpaceId(protectionSpace.getId()); + credentials = await this.credentialDao.getAllByProtectionSpaceId(protectionSpace.getId()!); } return credentials; } @@ -66,8 +66,7 @@ export default class CredentialDatabase { protectionSpaceId = protectionSpace.getId(); } - - let credential = await this.credentialDao.find(username, password, protectionSpaceId); + let credential = await this.credentialDao.find(username, password, protectionSpaceId!); if (credential != null) { let needUpdate = false; if (credential.getUsername() != username) { @@ -98,8 +97,10 @@ export default class CredentialDatabase { password: string) { let protectionSpace = await this.protectionSpaceDao.find(host, protocol, realm, port); if (protectionSpace != null) { - let credential = await this.credentialDao.find(username, password, protectionSpace.getId()); - this.credentialDao.delete(credential); + let credential = await this.credentialDao.find(username, password, protectionSpace.getId()!); + if (credential != null) { + this.credentialDao.delete(credential!); + } } } 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 99b0ca2c..a3e8285b 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 @@ -22,7 +22,7 @@ export default class HttpAuthenticationChallenge extends URLAuthenticationChalle private previousFailureCount: number proposedCredential: URLCredential | null - constructor(protectionSpace: URLProtectionSpace, previousFailureCount: number, proposedCredential: URLCredential) { + constructor(protectionSpace: URLProtectionSpace, previousFailureCount: number, proposedCredential: URLCredential | null) { super(protectionSpace) this.previousFailureCount = previousFailureCount this.proposedCredential = proposedCredential 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 8c9fd3e2..c5a66d93 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 @@ -16,6 +16,7 @@ import { Any } from '@ohos/flutter_ohos' import SslCertificate from './SslCertificate' import SslError from './SslError' +import { cert } from '@kit.DeviceCertificateKit' export default class URLProtectionSpace { private id: number | null = null @@ -23,11 +24,11 @@ export default class URLProtectionSpace { private protocol: string private realm: string | null private port: number - private sslCertificate: SslCertificate | null = null + private sslCertificate: cert.X509Cert | null = null private sslError: SslError | null = null - constructor(host: string, protocol: string, realm: string | null, port: number, id?: number, - sslCertificate?: SslCertificate, sslError?: SslError) { + constructor(host: string, protocol: string, realm: string | null, port: number, id?: number | null, + sslCertificate?: cert.X509Cert | null, sslError?: SslError | null) { this.host = host this.protocol = protocol this.realm = realm @@ -43,8 +44,8 @@ export default class URLProtectionSpace { } } - public toMap(): Map { + // TODO let urlProtectionSpaceMap: Map = new Map(); urlProtectionSpaceMap.set("host", this.host); urlProtectionSpaceMap.set("protocol", this.protocol); @@ -102,11 +103,11 @@ export default class URLProtectionSpace { this.port = port; } - public getSslCertificate(): SslCertificate | null { + public getSslCertificate(): cert.X509Cert | null { return this.sslCertificate; } - public setSslCertificate(sslCertificateExt: SslCertificate | null): void { + public setSslCertificate(sslCertificateExt: cert.X509Cert | null): void { this.sslCertificate = sslCertificateExt; } 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 7b3d18f8..9059ba42 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 @@ -40,11 +40,13 @@ import { JsBeforeUnloadCallback, JsConfirmCallback, JsPromptCallback, - PermissionRequestCallback + PermissionRequestCallback, + ReceivedHttpAuthRequestCallback } from '../WebViewChannelDelegate'; import JsAlertResponse from '../../types/JsAlertResponse'; import JsConfirmResponse from '../../types/JsConfirmResponse'; import JsPromptResponse from '../../types/JsPromptResponse'; +import HttpAuthResponse from '../../types/HttpAuthResponse'; import { ohosPromptDialogBuilder } from './OhosPromptDialog'; import { promptAction } from '@kit.ArkUI'; import JsBeforeUnloadResponse from '../../types/JsBeforeUnloadResponse'; @@ -53,13 +55,18 @@ import { BusinessError } from '@kit.BasicServicesKit'; import MimeTypes from '../../MimeTypes'; import PermissionResponse from '../../types/PermissionResponse'; import GeolocationPermissionShowPromptResponse from '../../types/GeolocationPermissionShowPromptResponse'; +import CredentialDatabase from '../../credential_database/CredentialDatabase'; +import HttpAuthenticationChallenge from '../../types/HttpAuthenticationChallenge'; +import URLProtectionSpace from '../../types/URLProtectionSpace'; +import { cert } from '@kit.DeviceCertificateKit' +import { List } from '@kit.ArkTS'; const TAG = "InAppWebViewChromeClient"; // 参考文档 所有事件 https://docs.openharmony.cn/pages/v4.1/zh-cn/application-dev/reference/apis-arkweb/ts-basic-components-web.md#onalert export default class InAppWebViewChromeClient { - private static previousAuthRequestFailureCount = 0; - private static credentialsProposed: Array | null = null; + public static previousAuthRequestFailureCount = 0; + public static credentialsProposed: List | null = null; private plugin: InAppWebViewFlutterPlugin; private inAppWebView: InAppWebView; private inAppBrowserDelegate: InAppBrowserDelegate | null = null; @@ -102,7 +109,8 @@ export default class InAppWebViewChromeClient { // 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)); + this.inAppWebView.channelDelegate.onJsPrompt(event.url, event.message, event.value, null, + new InnerJsPromptCallback(event.result, event.message, event.value, uiObject)); return true; } return false; @@ -443,8 +451,8 @@ export default class InAppWebViewChromeClient { return response; } onHttpAuthRequest = (event: Any) => { - // TODO Log.d(TAG, "onHttpAuthRequest=" + JSON.stringify(event)) + this.onReceivedHttpAuthRequest(event.handler, event.host, event.realm) return true; } onSslErrorEventReceive = (event: Any) => { @@ -616,6 +624,50 @@ export default class InAppWebViewChromeClient { return result == NavigationActionPolicy.CANCEL } + private async onReceivedHttpAuthRequest(handler: HttpAuthHandler, host: string, realm: string) { + let url = this.inAppWebView!.controller!.getUrl(); + let protocol = "https"; + let port = 0; + + if (url != null) { + try { + let uriurl = new uri.URI(url); + protocol = uriurl.scheme; + port = Number.parseInt(uriurl.port); + } catch (e) { + Log.e(TAG, "", e); + } + } + + InAppWebViewChromeClient.previousAuthRequestFailureCount++; + + if (InAppWebViewChromeClient.credentialsProposed == null) { + InAppWebViewChromeClient.credentialsProposed = await CredentialDatabase.getInstance(this.inAppWebView.context) + .getHttpAuthCredentials(host, protocol, realm, port); + } + + let credentialProposed: URLCredential | null = null; + if (InAppWebViewChromeClient.credentialsProposed != null && + InAppWebViewChromeClient.credentialsProposed.length > 0) { + credentialProposed = InAppWebViewChromeClient.credentialsProposed.get(0); + } + + 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, realm, port, null, certificate, null); + let challenge = new HttpAuthenticationChallenge(protectionSpace, InAppWebViewChromeClient.previousAuthRequestFailureCount, credentialProposed); + + let callback = new InnerReceivedHttpAuthRequestCallback(this.inAppWebView, handler, host, protocol, realm, port); + if (this.inAppWebView.channelDelegate != null) { + this.inAppWebView.channelDelegate.onReceivedHttpAuthRequest(challenge, callback); + } else { + callback.defaultBehaviour(null); + } + } + private loadCustomJavaScriptOnPageStarted(webView: InAppWebView) { let source = webView.userContentController.generateWrappedCodeForDocumentStart(); webView.controller.runJavaScriptExt(source) @@ -899,7 +951,7 @@ class InnerJsPromptCallback extends JsPromptCallback { }), alignment: DialogAlignment.Center, onDidDisappear: () => { - if(isCancel){ + if (isCancel) { result.handleCancel() } } @@ -1035,6 +1087,68 @@ class InnerGeolocationPermissionsShowPromptCallback extends GeolocationPermissio this.geolocation.invoke(this.origin, false, false); } + error(errorCode: string, errorMessage: string, errorDetails: Any): void { + Log.e(TAG, errorCode + ", " + ((errorMessage != null) ? errorMessage : "")); + this.defaultBehaviour(null); + } +} + +class InnerReceivedHttpAuthRequestCallback extends ReceivedHttpAuthRequestCallback { + private handler: HttpAuthHandler; + private host: string; + private finalProtocol: string; + private realm: string; + private finalPort: number; + private inAppWebView: InAppWebView; + + constructor(inAppWebView: InAppWebView, handler: HttpAuthHandler, host: string, protocol: string, realm: string, port: number) { + super(); + this.handler = handler; + this.host = host; + this.finalProtocol = protocol; + this.realm = realm; + this.finalPort = port; + this.inAppWebView = inAppWebView; + } + + nonNullSuccess(response: HttpAuthResponse): boolean { + let action = response.getAction(); + if (action != null) { + switch (action) { + case 1: + let username = response.getUsername(); + 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); + } + this.handler.confirm(username, password); + break; + case 2: + if (InAppWebViewChromeClient.credentialsProposed!.length > 0) { + let credential = InAppWebViewChromeClient.credentialsProposed!.removeByIndex(0); + this.handler.confirm(credential.getUsername(), credential.getPassword()); + } else { + this.handler.cancel(); + } + // used custom CredentialDatabase! + // handler.useHttpAuthUsernamePassword(); + break; + case 0: + default: + InAppWebViewChromeClient.credentialsProposed = null; + InAppWebViewChromeClient.previousAuthRequestFailureCount = 0; + this.handler.cancel(); + } + return false; + } + return true; + } + + defaultBehaviour(result: HttpAuthResponse | null): void { + this.handler.cancel(); + } + error(errorCode: string, errorMessage: string, errorDetails: Any): void { Log.e(TAG, errorCode + ", " + ((errorMessage != null) ? errorMessage : "")); this.defaultBehaviour(null); -- Gitee From 4d9db5118c79df2b4d92558bf098e0608197054a Mon Sep 17 00:00:00 2001 From: zhuzhengjun Date: Wed, 12 Jun 2024 10:37:38 +0800 Subject: [PATCH 4/4] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=8A=A0=E8=BD=BD?= =?UTF-8?q?=E8=84=9A=E6=9C=AC=E5=BC=82=E5=B8=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zhuzhengjun --- .../ets/components/plugin/EventConstant.ts | 1 + .../plugin/types/UserContentController.ets | 142 ++++++++++-------- .../components/plugin/types/UserScript.ets | 8 + .../webview/in_app_webview/OhosWebView.ets | 9 ++ 4 files changed, 98 insertions(+), 62 deletions(-) diff --git a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/EventConstant.ts b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/EventConstant.ts index df137f9b..5c3fee28 100644 --- a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/EventConstant.ts +++ b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/EventConstant.ts @@ -15,4 +15,5 @@ export default class EventConstant { public static readonly EVENT_PULL_SETREFRESHING = "pull_setRefreshing"; + public static readonly EVENT_UPDATE_STARTSCRIPTS = "update_startScripts"; } \ No newline at end of file diff --git a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/types/UserContentController.ets b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/types/UserContentController.ets index 2fc76c55..ebc523f2 100644 --- a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/types/UserContentController.ets +++ b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/types/UserContentController.ets @@ -19,10 +19,12 @@ import { Disposable } from './Disposable'; import PluginScript from './PluginScript'; import UserScript from './UserScript'; import { UserScriptInjectionTime } from './UserScriptInjectionTime'; -import { HashMap, HashSet } from '@kit.ArkTS'; +import { HashMap, HashSet, List } from '@kit.ArkTS'; import Util from '../Util'; import PluginScriptsUtil from '../plugin_scripts_js/PluginScriptsUtil'; import JavaScriptBridgeJS from '../plugin_scripts_js/JavaScriptBridgeJS'; +import { common } from '@kit.AbilityKit'; +import EventConstant from '../EventConstant' const DOCUMENT_READY_WRAPPER_JS_SOURCE = "if (document.readyState === 'interactive' || document.readyState === 'complete') { " + " " + PluginScriptsUtil.VAR_PLACEHOLDER_VALUE + @@ -90,6 +92,9 @@ export default class UserContentController implements Disposable { private userOnlyScripts = new HashMap>(); private pluginScripts = new HashMap>() private isSupportedDocumentStartScript = false + private allStartScriptItem = new List() + private contentWorldsCreatorScript: ScriptItem | null = null + private scriptHandlerMap = new HashMap() constructor(inAppWebView: InAppWebView) { this.inAppWebView = inAppWebView; @@ -181,20 +186,12 @@ export default class UserContentController implements Disposable { private updateContentWorldsCreatorScript(): void { let source: string = this.generateContentWorldsCreatorCode(); - // if (WebViewFeature.isFeatureSupported(WebViewFeature.DOCUMENT_START_SCRIPT)) { - // if (contentWorldsCreatorScript != null) { - // contentWorldsCreatorScript.remove(); - // } - // if (!source.isEmpty() && webView != null) { - // contentWorldsCreatorScript = WebViewCompat.addDocumentStartJavaScript( - // webView, - // source, - // new HashSet() {{ - // add("*"); - // }} - // ); - // } - // } + if (this.contentWorldsCreatorScript != null) { + this.allStartScriptItem.remove(this.contentWorldsCreatorScript) + } + if (source && source.length > 0) { + this.contentWorldsCreatorScript = this.addDocumentStartJavaScript(source, ["*"]); + } } public generateContentWorldsCreatorCode(): string { @@ -226,15 +223,14 @@ export default class UserContentController implements Disposable { this.contentWorlds.add(contentWorld); } this.updateContentWorldsCreatorScript(); - // if (this.webView != null && pluginScript.getInjectionTime() == UserScriptInjectionTime.AT_DOCUMENT_START - // && WebViewFeature.isFeatureSupported(WebViewFeature.DOCUMENT_START_SCRIPT)) { - // ScriptHandler scriptHandler = WebViewCompat.addDocumentStartJavaScript( - // webView, - // wrapSourceCodeInContentWorld(pluginScript.getContentWorld(), pluginScript.getSource()), - // pluginScript.getAllowedOriginRules() - // ); - // this.scriptHandlerMap.put(pluginScript, scriptHandler); - // } + if (pluginScript.getInjectionTime() == UserScriptInjectionTime.AT_DOCUMENT_START) { + let scriptHandler = this.addDocumentStartJavaScript( + this.wrapSourceCodeInContentWorld(pluginScript.getContentWorld(), pluginScript.getSource()), + pluginScript.getAllowedOriginRulesArray() + ); + this.scriptHandlerMap.set(pluginScript, scriptHandler); + } + this.onDocumentStartChanged() return this.pluginScripts.get(pluginScript.getInjectionTime()).add(pluginScript); } @@ -245,41 +241,38 @@ export default class UserContentController implements Disposable { } removePluginScript(pluginScript: PluginScript) { - // if (WebViewFeature.isFeatureSupported(WebViewFeature.DOCUMENT_START_SCRIPT)) { - // ScriptHandler scriptHandler = this.scriptHandlerMap.get(pluginScript); - // if (scriptHandler != null) { - // scriptHandler.remove(); - // this.scriptHandlerMap.remove(pluginScript); - // } - // this.updateContentWorldsCreatorScript(); - // } + let scriptHandler = this.scriptHandlerMap.get(pluginScript); + if (scriptHandler != null) { + this.allStartScriptItem.remove(scriptHandler); + this.scriptHandlerMap.remove(pluginScript); + this.updateContentWorldsCreatorScript(); + this.onDocumentStartChanged() + } return this.pluginScripts.get(pluginScript.getInjectionTime()).remove(pluginScript); } public removeAllUserOnlyScripts(): void { - // if (WebViewFeature.isFeatureSupported(WebViewFeature.DOCUMENT_START_SCRIPT)) { - // for (let userOnlyScript of this.userOnlyScripts.get(UserScriptInjectionTime.AT_DOCUMENT_START)) { - // ScriptHandler scriptHandler = this.scriptHandlerMap.get(userOnlyScript); - // if (scriptHandler != null) { - // scriptHandler.remove(); - // this.scriptHandlerMap.remove(userOnlyScript); - // } - // } - // } + for (let userOnlyScript of this.userOnlyScripts.get(UserScriptInjectionTime.AT_DOCUMENT_START)) { + let scriptHandler = this.scriptHandlerMap.get(userOnlyScript); + if (scriptHandler != null) { + this.allStartScriptItem.remove(scriptHandler); + this.scriptHandlerMap.remove(userOnlyScript); + } + } + this.onDocumentStartChanged() this.userOnlyScripts.get(UserScriptInjectionTime.AT_DOCUMENT_START).clear(); this.userOnlyScripts.get(UserScriptInjectionTime.AT_DOCUMENT_END).clear(); } public removeAllPluginScripts(): void { - // if (WebViewFeature.isFeatureSupported(WebViewFeature.DOCUMENT_START_SCRIPT)) { - // for (PluginScript pluginScript : this.pluginScripts.get(UserScriptInjectionTime.AT_DOCUMENT_START)) { - // ScriptHandler scriptHandler = this.scriptHandlerMap.get(pluginScript); - // if (scriptHandler != null) { - // scriptHandler.remove(); - // this.scriptHandlerMap.remove(pluginScript); - // } - // } - // } + for (let pluginScript of this.pluginScripts.get(UserScriptInjectionTime.AT_DOCUMENT_START)) { + let scriptHandler = this.scriptHandlerMap.get(pluginScript); + if (scriptHandler != null) { + this.allStartScriptItem.remove(scriptHandler); + this.scriptHandlerMap.remove(pluginScript); + } + } + this.onDocumentStartChanged() this.pluginScripts.get(UserScriptInjectionTime.AT_DOCUMENT_START).clear(); this.pluginScripts.get(UserScriptInjectionTime.AT_DOCUMENT_END).clear(); } @@ -289,7 +282,16 @@ export default class UserContentController implements Disposable { if (contentWorld != null) { this.contentWorlds.add(contentWorld); } - throw Error("Ohos currently does not support this feature") + this.updateContentWorldsCreatorScript(); + if (userOnlyScript.getInjectionTime() == UserScriptInjectionTime.AT_DOCUMENT_START) { + let scriptHandler = this.addDocumentStartJavaScript( + this.wrapSourceCodeInContentWorld(userOnlyScript.getContentWorld(), userOnlyScript.getSource()), + userOnlyScript.getAllowedOriginRulesArray() + ); + this.scriptHandlerMap.set(userOnlyScript, scriptHandler); + } + this.onDocumentStartChanged() + return this.userOnlyScripts.get(userOnlyScript.getInjectionTime()).add(userOnlyScript); } getUserOnlyScriptAsList(): HashSet { @@ -315,14 +317,13 @@ export default class UserContentController implements Disposable { } removeUserOnlyScript(userOnlyScript: UserScript): boolean { - // if (WebViewFeature.isFeatureSupported(WebViewFeature.DOCUMENT_START_SCRIPT)) { - // ScriptHandler scriptHandler = this.scriptHandlerMap.get(userOnlyScript); - // if (scriptHandler != null) { - // scriptHandler.remove(); - // this.scriptHandlerMap.remove(userOnlyScript); - // } - // this.updateContentWorldsCreatorScript(); - // } + let scriptHandler = this.scriptHandlerMap.get(userOnlyScript); + if (scriptHandler != null) { + this.allStartScriptItem.remove(scriptHandler); + this.scriptHandlerMap.remove(userOnlyScript); + this.updateContentWorldsCreatorScript(); + this.onDocumentStartChanged() + } return this.userOnlyScripts.get(userOnlyScript.getInjectionTime()).remove(userOnlyScript); } @@ -405,11 +406,28 @@ export default class UserContentController implements Disposable { } public dispose(): void { - // if (WebViewFeature.isFeatureSupported(WebViewFeature.DOCUMENT_START_SCRIPT) && contentWorldsCreatorScript != null) { - // contentWorldsCreatorScript.remove(); - // } + if (this.contentWorldsCreatorScript != null) { + this.allStartScriptItem.remove(this.contentWorldsCreatorScript) + } this.removeAllUserOnlyScripts(); this.removeAllPluginScripts(); this.inAppWebView = null; } + + private addDocumentStartJavaScript(source: string, scriptRule: Array): ScriptItem { + let scriptItem: ScriptItem = { + script: source, scriptRules: scriptRule + } + this.allStartScriptItem.add(scriptItem) + return scriptItem; + } + + getStartScripts() { + return this.allStartScriptItem.convertToArray() + } + + private onDocumentStartChanged(){ + let context = this.inAppWebView!.context as common.UIAbilityContext; + context.eventHub.emit(EventConstant.EVENT_UPDATE_STARTSCRIPTS, this.allStartScriptItem.convertToArray()) + } } \ No newline at end of file diff --git a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/types/UserScript.ets b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/types/UserScript.ets index c1517240..239a7627 100644 --- a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/types/UserScript.ets +++ b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/types/UserScript.ets @@ -90,6 +90,14 @@ export default class UserScript { return this.allowedOriginRules; } + getAllowedOriginRulesArray(): Array { + let rules = Array() + for (let valuesElement of this.allowedOriginRules.values()) { + rules.push(valuesElement); + } + return rules; + } + setAllowedOriginRules(allowedOriginRules: Set) { this.allowedOriginRules = allowedOriginRules; } diff --git a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/webview/in_app_webview/OhosWebView.ets b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/webview/in_app_webview/OhosWebView.ets index f353f549..32639a5f 100644 --- a/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/webview/in_app_webview/OhosWebView.ets +++ b/flutter_inappwebview_ohos/ohos/src/main/ets/components/plugin/webview/in_app_webview/OhosWebView.ets @@ -20,6 +20,7 @@ import { Params } from '@ohos/flutter_ohos/src/main/ets/plugin/platform/Platform import { FlutterWebView } from './FlutterWebView' import InAppWebView from './InAppWebView' import EventConstant from '../../EventConstant' +import { JSON } from '@kit.ArkTS'; @Component export struct OhosWebView { @@ -28,18 +29,25 @@ export struct OhosWebView { inAppWebView: InAppWebView | null = null @State isRefreshing: boolean = false @State isEnableRefresh: boolean = false + @State startScripts: Array = []; aboutToAppear(): void { this.isEnableRefresh = this.inAppWebView!.getPullToRefreshLayout().settings.enabled; + this.startScripts = this.inAppWebView!.userContentController.getStartScripts() let context = getContext() as common.UIAbilityContext; context.eventHub.on(EventConstant.EVENT_PULL_SETREFRESHING, (refreshing : boolean) => { this.isRefreshing = refreshing; }); + + context.eventHub.on(EventConstant.EVENT_UPDATE_STARTSCRIPTS, (scripts : Array) => { + this.startScripts = scripts; + }); } aboutToDisappear(): void { let context = getContext() as common.UIAbilityContext; context.eventHub.off(EventConstant.EVENT_PULL_SETREFRESHING); + context.eventHub.off(EventConstant.EVENT_UPDATE_STARTSCRIPTS); } build() { @@ -157,6 +165,7 @@ export struct OhosWebView { .allowWindowOpenMethod(this.inAppWebView!.customSettings.allowWindowOpenMethod) .layoutMode(this.inAppWebView!.customSettings.layoutMode) .enableNativeEmbedMode(this.inAppWebView!.customSettings.enableNativeEmbedMode) + .javaScriptOnDocumentStart(this.startScripts) } } -- Gitee