diff --git a/packages/webview_flutter/webview_flutter_android/CHANGELOG.md b/packages/webview_flutter/webview_flutter_android/CHANGELOG.md index 114f2a74eb..9dc13ccbd3 100644 --- a/packages/webview_flutter/webview_flutter_android/CHANGELOG.md +++ b/packages/webview_flutter/webview_flutter_android/CHANGELOG.md @@ -1,3 +1,7 @@ +## 3.9.0 + +* Adds support for `WebResouceError.url`. + ## 3.8.2 * Fixes unawaited_futures violations. diff --git a/packages/webview_flutter/webview_flutter_android/example/integration_test/webview_flutter_test.dart b/packages/webview_flutter/webview_flutter_android/example/integration_test/webview_flutter_test.dart index 462027ed97..53b8a0078f 100644 --- a/packages/webview_flutter/webview_flutter_android/example/integration_test/webview_flutter_test.dart +++ b/packages/webview_flutter/webview_flutter_android/example/integration_test/webview_flutter_test.dart @@ -826,9 +826,7 @@ Future main() async { expect(error.errorType, isNotNull); expect( - (error as AndroidWebResourceError) - .failingUrl - ?.startsWith('https://www.notawebsite..com'), + error.url?.startsWith('https://www.notawebsite..com'), isTrue, ); }); diff --git a/packages/webview_flutter/webview_flutter_android/example/lib/main.dart b/packages/webview_flutter/webview_flutter_android/example/lib/main.dart index b618c8f3e2..0c3e3411bd 100644 --- a/packages/webview_flutter/webview_flutter_android/example/lib/main.dart +++ b/packages/webview_flutter/webview_flutter_android/example/lib/main.dart @@ -114,6 +114,7 @@ Page resource error: description: ${error.description} errorType: ${error.errorType} isForMainFrame: ${error.isForMainFrame} + url: ${error.url} '''); }) ..setOnNavigationRequest((NavigationRequest request) { diff --git a/packages/webview_flutter/webview_flutter_android/example/pubspec.yaml b/packages/webview_flutter/webview_flutter_android/example/pubspec.yaml index 16cc964357..0b23ead3a9 100644 --- a/packages/webview_flutter/webview_flutter_android/example/pubspec.yaml +++ b/packages/webview_flutter/webview_flutter_android/example/pubspec.yaml @@ -17,7 +17,7 @@ dependencies: # The example app is bundled with the plugin so we use a path dependency on # the parent directory to use the current plugin's version. path: ../ - webview_flutter_platform_interface: ^2.3.0 + webview_flutter_platform_interface: ^2.4.0 dev_dependencies: espresso: ^0.2.0 diff --git a/packages/webview_flutter/webview_flutter_android/lib/src/android_webview_controller.dart b/packages/webview_flutter/webview_flutter_android/lib/src/android_webview_controller.dart index 6a4c918f95..7c5f0929de 100644 --- a/packages/webview_flutter/webview_flutter_android/lib/src/android_webview_controller.dart +++ b/packages/webview_flutter/webview_flutter_android/lib/src/android_webview_controller.dart @@ -825,12 +825,14 @@ class AndroidWebResourceError extends WebResourceError { required super.errorCode, required super.description, super.isForMainFrame, - this.failingUrl, - }) : super( + super.url, + }) : failingUrl = url, + super( errorType: _errorCodeToErrorType(errorCode), ); /// Gets the URL for which the failing resource request was made. + @Deprecated('Please use `url`.') final String? failingUrl; static WebResourceErrorType? _errorCodeToErrorType(int errorCode) { @@ -954,7 +956,7 @@ class AndroidNavigationDelegate extends PlatformNavigationDelegate { callback(AndroidWebResourceError._( errorCode: error.errorCode, description: error.description, - failingUrl: request.url, + url: request.url, isForMainFrame: request.isForMainFrame, )); } @@ -971,7 +973,7 @@ class AndroidNavigationDelegate extends PlatformNavigationDelegate { callback(AndroidWebResourceError._( errorCode: errorCode, description: description, - failingUrl: failingUrl, + url: failingUrl, isForMainFrame: true, )); } diff --git a/packages/webview_flutter/webview_flutter_android/pubspec.yaml b/packages/webview_flutter/webview_flutter_android/pubspec.yaml index a58c031b82..6755ed363b 100644 --- a/packages/webview_flutter/webview_flutter_android/pubspec.yaml +++ b/packages/webview_flutter/webview_flutter_android/pubspec.yaml @@ -2,7 +2,7 @@ name: webview_flutter_android description: A Flutter plugin that provides a WebView widget on Android. repository: https://github.com/flutter/packages/tree/main/packages/webview_flutter/webview_flutter_android issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+webview%22 -version: 3.8.2 +version: 3.9.0 environment: sdk: ">=2.18.0 <4.0.0" @@ -20,7 +20,7 @@ flutter: dependencies: flutter: sdk: flutter - webview_flutter_platform_interface: ^2.3.0 + webview_flutter_platform_interface: ^2.4.0 dev_dependencies: build_runner: ^2.1.4 diff --git a/packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md b/packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md index e24e3e0f00..26cd8a2a42 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md +++ b/packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md @@ -1,3 +1,7 @@ +## 3.7.0 + +* Adds support for `WebResouceError.url`. + ## 3.6.3 * Introduces `NSError.toString` for better diagnostics. @@ -16,7 +20,7 @@ * Adds support to enable debugging of web contents on the latest versions of WebKit. See `WebKitWebViewController.setInspectable`. - + ## 3.5.0 * Adds support to limit navigation to pages within the app’s domain. See diff --git a/packages/webview_flutter/webview_flutter_wkwebview/example/integration_test/webview_flutter_test.dart b/packages/webview_flutter/webview_flutter_wkwebview/example/integration_test/webview_flutter_test.dart index 4b457d0e4c..edbe5e366f 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/example/integration_test/webview_flutter_test.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/example/integration_test/webview_flutter_test.dart @@ -834,6 +834,10 @@ Future main() async { final WebResourceError error = await errorCompleter.future; expect(error, isNotNull); + expect( + error.url?.startsWith('https://www.notawebsite..com'), + isTrue, + ); expect((error as WebKitWebResourceError).domain, isNotNull); }); diff --git a/packages/webview_flutter/webview_flutter_wkwebview/example/ios/Runner.xcodeproj/project.pbxproj b/packages/webview_flutter/webview_flutter_wkwebview/example/ios/Runner.xcodeproj/project.pbxproj index 19e2b39a5c..32c0bf9872 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/webview_flutter/webview_flutter_wkwebview/example/ios/Runner.xcodeproj/project.pbxproj @@ -11,6 +11,7 @@ 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 8F4FF949299ADC2D000A6586 /* FWFWebViewFlutterWKWebViewExternalAPITests.m in Sources */ = {isa = PBXBuildFile; fileRef = 8F4FF948299ADC2D000A6586 /* FWFWebViewFlutterWKWebViewExternalAPITests.m */; }; 8F4FF94B29AC223F000A6586 /* FWFURLTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 8F4FF94A29AC223F000A6586 /* FWFURLTests.m */; }; + 8F78EAAA2A02CB9100C2E520 /* FWFErrorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 8F78EAA92A02CB9100C2E520 /* FWFErrorTests.m */; }; 8FA6A87928062CD000A4B183 /* FWFInstanceManagerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 8FA6A87828062CD000A4B183 /* FWFInstanceManagerTests.m */; }; 8FB79B5328134C3100C101D3 /* FWFWebViewHostApiTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 8FB79B5228134C3100C101D3 /* FWFWebViewHostApiTests.m */; }; 8FB79B55281B24F600C101D3 /* FWFDataConvertersTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 8FB79B54281B24F600C101D3 /* FWFDataConvertersTests.m */; }; @@ -80,6 +81,7 @@ 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 8F4FF948299ADC2D000A6586 /* FWFWebViewFlutterWKWebViewExternalAPITests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FWFWebViewFlutterWKWebViewExternalAPITests.m; sourceTree = ""; }; 8F4FF94A29AC223F000A6586 /* FWFURLTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FWFURLTests.m; sourceTree = ""; }; + 8F78EAA92A02CB9100C2E520 /* FWFErrorTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FWFErrorTests.m; sourceTree = ""; }; 8FA6A87828062CD000A4B183 /* FWFInstanceManagerTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FWFInstanceManagerTests.m; sourceTree = ""; }; 8FB79B5228134C3100C101D3 /* FWFWebViewHostApiTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FWFWebViewHostApiTests.m; sourceTree = ""; }; 8FB79B54281B24F600C101D3 /* FWFDataConvertersTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FWFDataConvertersTests.m; sourceTree = ""; }; @@ -165,6 +167,7 @@ 8FB79B902820BAC700C101D3 /* FWFUIViewHostApiTests.m */, 8FB79B962821985200C101D3 /* FWFObjectHostApiTests.m */, 8F4FF94A29AC223F000A6586 /* FWFURLTests.m */, + 8F78EAA92A02CB9100C2E520 /* FWFErrorTests.m */, ); path = RunnerTests; sourceTree = ""; @@ -466,6 +469,7 @@ buildActionMask = 2147483647; files = ( 8FA6A87928062CD000A4B183 /* FWFInstanceManagerTests.m in Sources */, + 8F78EAAA2A02CB9100C2E520 /* FWFErrorTests.m in Sources */, 8F4FF94B29AC223F000A6586 /* FWFURLTests.m in Sources */, 8FB79B852820A3A400C101D3 /* FWFUIDelegateHostApiTests.m in Sources */, 8FB79B972821985200C101D3 /* FWFObjectHostApiTests.m in Sources */, diff --git a/packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerTests/FWFDataConvertersTests.m b/packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerTests/FWFDataConvertersTests.m index f580b6022c..1a64148b48 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerTests/FWFDataConvertersTests.m +++ b/packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerTests/FWFDataConvertersTests.m @@ -98,14 +98,20 @@ } - (void)testFWFNSErrorDataFromNSError { + NSObject *unsupportedType = [[NSObject alloc] init]; NSError *error = [NSError errorWithDomain:@"domain" code:23 - userInfo:@{NSLocalizedDescriptionKey : @"description"}]; + userInfo:@{@"a" : @"b", @"c" : unsupportedType}]; FWFNSErrorData *data = FWFNSErrorDataFromNativeNSError(error); XCTAssertEqualObjects(data.code, @23); XCTAssertEqualObjects(data.domain, @"domain"); - XCTAssertEqualObjects(data.localizedDescription, @"description"); + + NSDictionary *userInfo = @{ + @"a" : @"b", + @"c" : [NSString stringWithFormat:@"Unsupported Type: %@", unsupportedType.description] + }; + XCTAssertEqualObjects(data.userInfo, userInfo); } - (void)testFWFWKScriptMessageDataFromWKScriptMessage { diff --git a/packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerTests/FWFErrorTests.m b/packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerTests/FWFErrorTests.m new file mode 100644 index 0000000000..422b7e49ae --- /dev/null +++ b/packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerTests/FWFErrorTests.m @@ -0,0 +1,18 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +@import XCTest; + +#import + +@interface FWFErrorTests : XCTestCase +@end + +@implementation FWFErrorTests +- (void)testNSErrorUserInfoKey { + // These MUST match the String values in the Dart class NSErrorUserInfoKey. + XCTAssertEqualObjects(NSLocalizedDescriptionKey, @"NSLocalizedDescription"); + XCTAssertEqualObjects(NSURLErrorFailingURLStringErrorKey, @"NSErrorFailingURLStringKey"); +} +@end diff --git a/packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerTests/FWFWebViewHostApiTests.m b/packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerTests/FWFWebViewHostApiTests.m index 248f947a84..a89bf338c3 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerTests/FWFWebViewHostApiTests.m +++ b/packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerTests/FWFWebViewHostApiTests.m @@ -408,7 +408,7 @@ static bool feq(CGFloat a, CGFloat b) { return fabs(b - a) < FLT_EPSILON; } XCTAssertTrue([errorData isKindOfClass:[FWFNSErrorData class]]); XCTAssertEqualObjects(errorData.code, @0); XCTAssertEqualObjects(errorData.domain, @"errorDomain"); - XCTAssertEqualObjects(errorData.localizedDescription, @"description"); + XCTAssertEqualObjects(errorData.userInfo, @{NSLocalizedDescriptionKey : @"description"}); } - (void)testWebViewContentInsetBehaviorShouldBeNever { diff --git a/packages/webview_flutter/webview_flutter_wkwebview/example/lib/main.dart b/packages/webview_flutter/webview_flutter_wkwebview/example/lib/main.dart index 8c3f753129..7367828dbe 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/example/lib/main.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/example/lib/main.dart @@ -115,6 +115,7 @@ Page resource error: description: ${error.description} errorType: ${error.errorType} isForMainFrame: ${error.isForMainFrame} + url: ${error.url} '''); }) ..setOnNavigationRequest((NavigationRequest request) { diff --git a/packages/webview_flutter/webview_flutter_wkwebview/example/pubspec.yaml b/packages/webview_flutter/webview_flutter_wkwebview/example/pubspec.yaml index 2ddb76ad79..aae7c82df0 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/example/pubspec.yaml +++ b/packages/webview_flutter/webview_flutter_wkwebview/example/pubspec.yaml @@ -10,7 +10,7 @@ dependencies: flutter: sdk: flutter path_provider: ^2.0.6 - webview_flutter_platform_interface: ^2.3.0 + webview_flutter_platform_interface: ^2.4.0 webview_flutter_wkwebview: # When depending on this package from a real application you should use: # webview_flutter: ^x.y.z diff --git a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFDataConverters.m b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFDataConverters.m index 20607daf4a..28c029888a 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFDataConverters.m +++ b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFDataConverters.m @@ -192,9 +192,19 @@ WKNavigationActionPolicy FWFNativeWKNavigationActionPolicyFromEnumData( } FWFNSErrorData *FWFNSErrorDataFromNativeNSError(NSError *error) { - return [FWFNSErrorData makeWithCode:@(error.code) - domain:error.domain - localizedDescription:error.localizedDescription]; + NSMutableDictionary *userInfo; + if (error.userInfo) { + userInfo = [NSMutableDictionary dictionary]; + for (NSErrorUserInfoKey key in error.userInfo.allKeys) { + NSObject *value = error.userInfo[key]; + if ([value isKindOfClass:[NSString class]]) { + userInfo[key] = value; + } else { + userInfo[key] = [NSString stringWithFormat:@"Unsupported Type: %@", value.description]; + } + } + } + return [FWFNSErrorData makeWithCode:@(error.code) domain:error.domain userInfo:userInfo]; } FWFNSKeyValueChangeKeyEnumData *FWFNSKeyValueChangeKeyEnumDataFromNativeNSKeyValueChangeKey( diff --git a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFGeneratedWebKitApis.h b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFGeneratedWebKitApis.h index e302568d8d..3aa3fb7c99 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFGeneratedWebKitApis.h +++ b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFGeneratedWebKitApis.h @@ -342,10 +342,10 @@ typedef NS_ENUM(NSUInteger, FWFWKMediaCaptureType) { - (instancetype)init NS_UNAVAILABLE; + (instancetype)makeWithCode:(NSNumber *)code domain:(NSString *)domain - localizedDescription:(NSString *)localizedDescription; + userInfo:(nullable NSDictionary *)userInfo; @property(nonatomic, strong) NSNumber *code; @property(nonatomic, copy) NSString *domain; -@property(nonatomic, copy) NSString *localizedDescription; +@property(nonatomic, strong, nullable) NSDictionary *userInfo; @end /// Mirror of WKScriptMessage. diff --git a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFGeneratedWebKitApis.m b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFGeneratedWebKitApis.m index 8104a5df99..66264ebe31 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFGeneratedWebKitApis.m +++ b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFGeneratedWebKitApis.m @@ -455,11 +455,11 @@ static id GetNullableObjectAtIndex(NSArray *array, NSInteger key) { @implementation FWFNSErrorData + (instancetype)makeWithCode:(NSNumber *)code domain:(NSString *)domain - localizedDescription:(NSString *)localizedDescription { + userInfo:(nullable NSDictionary *)userInfo { FWFNSErrorData *pigeonResult = [[FWFNSErrorData alloc] init]; pigeonResult.code = code; pigeonResult.domain = domain; - pigeonResult.localizedDescription = localizedDescription; + pigeonResult.userInfo = userInfo; return pigeonResult; } + (FWFNSErrorData *)fromList:(NSArray *)list { @@ -468,8 +468,7 @@ static id GetNullableObjectAtIndex(NSArray *array, NSInteger key) { NSAssert(pigeonResult.code != nil, @""); pigeonResult.domain = GetNullableObjectAtIndex(list, 1); NSAssert(pigeonResult.domain != nil, @""); - pigeonResult.localizedDescription = GetNullableObjectAtIndex(list, 2); - NSAssert(pigeonResult.localizedDescription != nil, @""); + pigeonResult.userInfo = GetNullableObjectAtIndex(list, 2); return pigeonResult; } + (nullable FWFNSErrorData *)nullableFromList:(NSArray *)list { @@ -479,7 +478,7 @@ static id GetNullableObjectAtIndex(NSArray *array, NSInteger key) { return @[ (self.code ?: [NSNull null]), (self.domain ?: [NSNull null]), - (self.localizedDescription ?: [NSNull null]), + (self.userInfo ?: [NSNull null]), ]; } @end diff --git a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/common/web_kit.g.dart b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/common/web_kit.g.dart index 91c81feb36..0f7fd8fa0f 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/common/web_kit.g.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/common/web_kit.g.dart @@ -522,20 +522,20 @@ class NSErrorData { NSErrorData({ required this.code, required this.domain, - required this.localizedDescription, + this.userInfo, }); int code; String domain; - String localizedDescription; + Map? userInfo; Object encode() { return [ code, domain, - localizedDescription, + userInfo, ]; } @@ -544,7 +544,7 @@ class NSErrorData { return NSErrorData( code: result[0]! as int, domain: result[1]! as String, - localizedDescription: result[2]! as String, + userInfo: (result[2] as Map?)?.cast(), ); } } diff --git a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/foundation/foundation.dart b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/foundation/foundation.dart index e8dde5e03d..3fe1a57c1b 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/foundation/foundation.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/foundation/foundation.dart @@ -201,6 +201,23 @@ class NSUrlRequest { final Map allHttpHeaderFields; } +/// Keys that may exist in the user info map of `NSError`. +class NSErrorUserInfoKey { + NSErrorUserInfoKey._(); + + /// The corresponding value is a localized string representation of the error + /// that, if present, will be returned by [NSError.localizedDescription]. + /// + /// See https://developer.apple.com/documentation/foundation/nslocalizeddescriptionkey. + static const String NSLocalizedDescription = 'NSLocalizedDescription'; + + /// The URL which caused a load to fail. + /// + /// See https://developer.apple.com/documentation/foundation/nsurlerrorfailingurlstringerrorkey?language=objc. + static const String NSURLErrorFailingURLStringError = + 'NSErrorFailingURLStringKey'; +} + /// Information about an error condition. /// /// Wraps [NSError](https://developer.apple.com/documentation/foundation/nserror?language=objc). @@ -210,7 +227,7 @@ class NSError { const NSError({ required this.code, required this.domain, - required this.localizedDescription, + this.userInfo = const {}, }); /// The error code. @@ -221,15 +238,23 @@ class NSError { /// A string containing the error domain. final String domain; + /// Map of arbitrary data. + /// + /// See [NSErrorUserInfoKey] for possible keys (non-exhaustive). + /// + /// This currently only supports values that are a String. + final Map userInfo; + /// A string containing the localized description of the error. - final String localizedDescription; + String? get localizedDescription => + userInfo[NSErrorUserInfoKey.NSLocalizedDescription] as String?; @override String toString() { - if (localizedDescription.isEmpty) { - return 'Error $domain:$code'; + if (localizedDescription?.isEmpty ?? true) { + return 'Error $domain:$code:$userInfo'; } - return '$localizedDescription ($domain:$code)'; + return '$localizedDescription ($domain:$code:$userInfo)'; } } diff --git a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/legacy/web_kit_webview_widget.dart b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/legacy/web_kit_webview_widget.dart index da0745a442..f344edb00b 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/legacy/web_kit_webview_widget.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/legacy/web_kit_webview_widget.dart @@ -596,7 +596,7 @@ class WebKitWebViewPlatformController extends WebViewPlatformController { return WebResourceError( errorCode: error.code, domain: error.domain, - description: error.localizedDescription, + description: error.localizedDescription ?? '', errorType: errorType, ); } diff --git a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/web_kit/web_kit_api_impls.dart b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/web_kit/web_kit_api_impls.dart index b0ce519156..ccc87377cb 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/web_kit/web_kit_api_impls.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/web_kit/web_kit_api_impls.dart @@ -199,7 +199,7 @@ extension _WKNSErrorDataConverter on NSErrorData { return NSError( domain: domain, code: code, - localizedDescription: localizedDescription, + userInfo: userInfo?.cast() ?? {}, ); } } diff --git a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_webview_controller.dart b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_webview_controller.dart index 5df538ca0c..14cba330a7 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_webview_controller.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_webview_controller.dart @@ -665,10 +665,13 @@ class WebKitWebViewWidget extends PlatformWebViewWidget { /// An implementation of [WebResourceError] with the WebKit API. class WebKitWebResourceError extends WebResourceError { - WebKitWebResourceError._(this._nsError, {required bool isForMainFrame}) - : super( + WebKitWebResourceError._( + this._nsError, { + required bool isForMainFrame, + required super.url, + }) : super( errorCode: _nsError.code, - description: _nsError.localizedDescription, + description: _nsError.localizedDescription ?? '', errorType: _toWebResourceErrorType(_nsError.code), isForMainFrame: isForMainFrame, ); @@ -766,14 +769,24 @@ class WebKitNavigationDelegate extends PlatformNavigationDelegate { didFailNavigation: (WKWebView webView, NSError error) { if (weakThis.target?._onWebResourceError != null) { weakThis.target!._onWebResourceError!( - WebKitWebResourceError._(error, isForMainFrame: true), + WebKitWebResourceError._( + error, + isForMainFrame: true, + url: error.userInfo[NSErrorUserInfoKey + .NSURLErrorFailingURLStringError] as String?, + ), ); } }, didFailProvisionalNavigation: (WKWebView webView, NSError error) { if (weakThis.target?._onWebResourceError != null) { weakThis.target!._onWebResourceError!( - WebKitWebResourceError._(error, isForMainFrame: true), + WebKitWebResourceError._( + error, + isForMainFrame: true, + url: error.userInfo[NSErrorUserInfoKey + .NSURLErrorFailingURLStringError] as String?, + ), ); } }, @@ -785,9 +798,9 @@ class WebKitNavigationDelegate extends PlatformNavigationDelegate { code: WKErrorCode.webContentProcessTerminated, // Value from https://developer.apple.com/documentation/webkit/wkerrordomain?language=objc. domain: 'WKErrorDomain', - localizedDescription: '', ), isForMainFrame: true, + url: null, ), ); } diff --git a/packages/webview_flutter/webview_flutter_wkwebview/pigeons/web_kit.dart b/packages/webview_flutter/webview_flutter_wkwebview/pigeons/web_kit.dart index 16248e88de..dea5080e55 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/pigeons/web_kit.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/pigeons/web_kit.dart @@ -299,7 +299,7 @@ class WKFrameInfoData { class NSErrorData { late int code; late String domain; - late String localizedDescription; + late Map? userInfo; } /// Mirror of WKScriptMessage. diff --git a/packages/webview_flutter/webview_flutter_wkwebview/pubspec.yaml b/packages/webview_flutter/webview_flutter_wkwebview/pubspec.yaml index 9c313c01ef..a88d74d61d 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/pubspec.yaml +++ b/packages/webview_flutter/webview_flutter_wkwebview/pubspec.yaml @@ -2,7 +2,7 @@ name: webview_flutter_wkwebview description: A Flutter plugin that provides a WebView widget based on Apple's WKWebView control. repository: https://github.com/flutter/packages/tree/main/packages/webview_flutter/webview_flutter_wkwebview issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+webview%22 -version: 3.6.3 +version: 3.7.0 environment: sdk: ">=2.18.0 <4.0.0" @@ -20,7 +20,7 @@ dependencies: flutter: sdk: flutter path: ^1.8.0 - webview_flutter_platform_interface: ^2.3.0 + webview_flutter_platform_interface: ^2.4.0 dev_dependencies: build_runner: ^2.1.5 diff --git a/packages/webview_flutter/webview_flutter_wkwebview/test/legacy/web_kit_webview_widget_test.dart b/packages/webview_flutter/webview_flutter_wkwebview/test/legacy/web_kit_webview_widget_test.dart index 9388bddd55..2033d39c98 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/test/legacy/web_kit_webview_widget_test.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/test/legacy/web_kit_webview_widget_test.dart @@ -777,7 +777,6 @@ void main() { details: const NSError( code: WKErrorCode.javaScriptResultTypeIsUnsupported, domain: '', - localizedDescription: '', ), )); expect( @@ -1049,7 +1048,9 @@ void main() { const NSError( code: WKErrorCode.webViewInvalidated, domain: 'domain', - localizedDescription: 'my desc', + userInfo: { + NSErrorUserInfoKey.NSLocalizedDescription: 'my desc', + }, ), ); @@ -1086,7 +1087,9 @@ void main() { const NSError( code: WKErrorCode.webContentProcessTerminated, domain: 'domain', - localizedDescription: 'my desc', + userInfo: { + NSErrorUserInfoKey.NSLocalizedDescription: 'my desc', + }, ), ); diff --git a/packages/webview_flutter/webview_flutter_wkwebview/test/src/foundation/foundation_test.dart b/packages/webview_flutter/webview_flutter_wkwebview/test/src/foundation/foundation_test.dart index 3dbaea08ed..ea2e37e2cd 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/test/src/foundation/foundation_test.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/test/src/foundation/foundation_test.dart @@ -252,33 +252,41 @@ void main() { const NSError( code: 0, domain: 'domain', - localizedDescription: 'desc', + userInfo: { + NSErrorUserInfoKey.NSLocalizedDescription: 'desc', + }, ).toString(), - 'desc (domain:0)', + 'desc (domain:0:{NSLocalizedDescription: desc})', ); expect( const NSError( code: 0, domain: 'domain', - localizedDescription: '', + userInfo: { + NSErrorUserInfoKey.NSLocalizedDescription: '', + }, ).toString(), - 'Error domain:0', + 'Error domain:0:{NSLocalizedDescription: }', ); expect( const NSError( code: 255, domain: 'bar', - localizedDescription: 'baz', + userInfo: { + NSErrorUserInfoKey.NSLocalizedDescription: 'baz', + }, ).toString(), - 'baz (bar:255)', + 'baz (bar:255:{NSLocalizedDescription: baz})', ); expect( const NSError( code: 255, domain: 'bar', - localizedDescription: '', + userInfo: { + NSErrorUserInfoKey.NSLocalizedDescription: '', + }, ).toString(), - 'Error bar:255', + 'Error bar:255:{NSLocalizedDescription: }', ); }); } diff --git a/packages/webview_flutter/webview_flutter_wkwebview/test/src/web_kit/web_kit_test.dart b/packages/webview_flutter/webview_flutter_wkwebview/test/src/web_kit/web_kit_test.dart index 856ca55e7c..055f342ab7 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/test/src/web_kit/web_kit_test.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/test/src/web_kit/web_kit_test.dart @@ -614,7 +614,9 @@ void main() { NSErrorData( code: 23, domain: 'Hello', - localizedDescription: 'localiziedDescription', + userInfo: { + NSErrorUserInfoKey.NSLocalizedDescription: 'my desc', + }, ), ); @@ -646,7 +648,9 @@ void main() { NSErrorData( code: 23, domain: 'Hello', - localizedDescription: 'localiziedDescription', + userInfo: { + NSErrorUserInfoKey.NSLocalizedDescription: 'my desc', + }, ), ); @@ -851,7 +855,9 @@ void main() { details: NSErrorData( code: 0, domain: 'domain', - localizedDescription: 'desc', + userInfo: { + NSErrorUserInfoKey.NSLocalizedDescription: 'desc', + }, ), ), ); diff --git a/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_navigation_delegate_test.dart b/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_navigation_delegate_test.dart index 0f754cb7f0..4581c92b78 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_navigation_delegate_test.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_navigation_delegate_test.dart @@ -92,12 +92,17 @@ void main() { const NSError( code: WKErrorCode.webViewInvalidated, domain: 'domain', - localizedDescription: 'my desc', + userInfo: { + NSErrorUserInfoKey.NSURLErrorFailingURLStringError: + 'www.flutter.dev', + NSErrorUserInfoKey.NSLocalizedDescription: 'my desc', + }, ), ); expect(callbackError.description, 'my desc'); expect(callbackError.errorCode, WKErrorCode.webViewInvalidated); + expect(callbackError.url, 'www.flutter.dev'); expect(callbackError.domain, 'domain'); expect(callbackError.errorType, WebResourceErrorType.webViewInvalidated); expect(callbackError.isForMainFrame, true); @@ -126,11 +131,16 @@ void main() { const NSError( code: WKErrorCode.webViewInvalidated, domain: 'domain', - localizedDescription: 'my desc', + userInfo: { + NSErrorUserInfoKey.NSURLErrorFailingURLStringError: + 'www.flutter.dev', + NSErrorUserInfoKey.NSLocalizedDescription: 'my desc', + }, ), ); expect(callbackError.description, 'my desc'); + expect(callbackError.url, 'www.flutter.dev'); expect(callbackError.errorCode, WKErrorCode.webViewInvalidated); expect(callbackError.domain, 'domain'); expect(callbackError.errorType, WebResourceErrorType.webViewInvalidated); diff --git a/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_controller_test.dart b/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_controller_test.dart index 89df6340d1..2cd20e0f68 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_controller_test.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_controller_test.dart @@ -502,7 +502,6 @@ void main() { details: const NSError( code: WKErrorCode.javaScriptResultTypeIsUnsupported, domain: '', - localizedDescription: '', ), )); expect(