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 c48b313daec2..e7519af18e7c 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 @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 46; + objectVersion = 50; objects = { /* Begin PBXBuildFile section */ @@ -14,6 +14,17 @@ 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 */; }; + 8FB79B672820453400C101D3 /* FWFHTTPCookieStoreHostApiTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 8FB79B662820453400C101D3 /* FWFHTTPCookieStoreHostApiTests.m */; }; + 8FB79B6928204E8700C101D3 /* FWFPreferencesHostApiTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 8FB79B6828204E8700C101D3 /* FWFPreferencesHostApiTests.m */; }; + 8FB79B6B28204EE500C101D3 /* FWFWebsiteDataStoreHostApiTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 8FB79B6A28204EE500C101D3 /* FWFWebsiteDataStoreHostApiTests.m */; }; + 8FB79B6D2820533B00C101D3 /* FWFWebViewConfigurationHostApiTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 8FB79B6C2820533B00C101D3 /* FWFWebViewConfigurationHostApiTests.m */; }; + 8FB79B73282096B500C101D3 /* FWFScriptMessageHandlerHostApiTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 8FB79B72282096B500C101D3 /* FWFScriptMessageHandlerHostApiTests.m */; }; + 8FB79B7928209D1300C101D3 /* FWFUserContentControllerHostApiTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 8FB79B7828209D1300C101D3 /* FWFUserContentControllerHostApiTests.m */; }; + 8FB79B832820A39300C101D3 /* FWFNavigationDelegateHostApiTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 8FB79B822820A39300C101D3 /* FWFNavigationDelegateHostApiTests.m */; }; + 8FB79B852820A3A400C101D3 /* FWFUIDelegateHostApiTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 8FB79B842820A3A400C101D3 /* FWFUIDelegateHostApiTests.m */; }; + 8FB79B8F2820BAB300C101D3 /* FWFScrollViewHostApiTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 8FB79B8E2820BAB300C101D3 /* FWFScrollViewHostApiTests.m */; }; + 8FB79B912820BAC700C101D3 /* FWFUIViewHostApiTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 8FB79B902820BAC700C101D3 /* FWFUIViewHostApiTests.m */; }; + 8FB79B972821985200C101D3 /* FWFObjectHostApiTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 8FB79B962821985200C101D3 /* FWFObjectHostApiTests.m */; }; 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; }; 97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; @@ -73,6 +84,17 @@ 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 = ""; }; + 8FB79B662820453400C101D3 /* FWFHTTPCookieStoreHostApiTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FWFHTTPCookieStoreHostApiTests.m; sourceTree = ""; }; + 8FB79B6828204E8700C101D3 /* FWFPreferencesHostApiTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FWFPreferencesHostApiTests.m; sourceTree = ""; }; + 8FB79B6A28204EE500C101D3 /* FWFWebsiteDataStoreHostApiTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FWFWebsiteDataStoreHostApiTests.m; sourceTree = ""; }; + 8FB79B6C2820533B00C101D3 /* FWFWebViewConfigurationHostApiTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FWFWebViewConfigurationHostApiTests.m; sourceTree = ""; }; + 8FB79B72282096B500C101D3 /* FWFScriptMessageHandlerHostApiTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FWFScriptMessageHandlerHostApiTests.m; sourceTree = ""; }; + 8FB79B7828209D1300C101D3 /* FWFUserContentControllerHostApiTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FWFUserContentControllerHostApiTests.m; sourceTree = ""; }; + 8FB79B822820A39300C101D3 /* FWFNavigationDelegateHostApiTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FWFNavigationDelegateHostApiTests.m; sourceTree = ""; }; + 8FB79B842820A3A400C101D3 /* FWFUIDelegateHostApiTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FWFUIDelegateHostApiTests.m; sourceTree = ""; }; + 8FB79B8E2820BAB300C101D3 /* FWFScrollViewHostApiTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FWFScrollViewHostApiTests.m; sourceTree = ""; }; + 8FB79B902820BAC700C101D3 /* FWFUIViewHostApiTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FWFUIViewHostApiTests.m; sourceTree = ""; }; + 8FB79B962821985200C101D3 /* FWFObjectHostApiTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FWFObjectHostApiTests.m; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -135,6 +157,17 @@ 8FA6A87828062CD000A4B183 /* FWFInstanceManagerTests.m */, 8FB79B5228134C3100C101D3 /* FWFWebViewHostApiTests.m */, 8FB79B54281B24F600C101D3 /* FWFDataConvertersTests.m */, + 8FB79B662820453400C101D3 /* FWFHTTPCookieStoreHostApiTests.m */, + 8FB79B6828204E8700C101D3 /* FWFPreferencesHostApiTests.m */, + 8FB79B6A28204EE500C101D3 /* FWFWebsiteDataStoreHostApiTests.m */, + 8FB79B6C2820533B00C101D3 /* FWFWebViewConfigurationHostApiTests.m */, + 8FB79B72282096B500C101D3 /* FWFScriptMessageHandlerHostApiTests.m */, + 8FB79B7828209D1300C101D3 /* FWFUserContentControllerHostApiTests.m */, + 8FB79B822820A39300C101D3 /* FWFNavigationDelegateHostApiTests.m */, + 8FB79B842820A3A400C101D3 /* FWFUIDelegateHostApiTests.m */, + 8FB79B8E2820BAB300C101D3 /* FWFScrollViewHostApiTests.m */, + 8FB79B902820BAC700C101D3 /* FWFUIViewHostApiTests.m */, + 8FB79B962821985200C101D3 /* FWFObjectHostApiTests.m */, ); path = RunnerTests; sourceTree = ""; @@ -433,11 +466,22 @@ buildActionMask = 2147483647; files = ( 8FA6A87928062CD000A4B183 /* FWFInstanceManagerTests.m in Sources */, + 8FB79B852820A3A400C101D3 /* FWFUIDelegateHostApiTests.m in Sources */, + 8FB79B972821985200C101D3 /* FWFObjectHostApiTests.m in Sources */, + 8FB79B672820453400C101D3 /* FWFHTTPCookieStoreHostApiTests.m in Sources */, 8FB79B5328134C3100C101D3 /* FWFWebViewHostApiTests.m in Sources */, + 8FB79B73282096B500C101D3 /* FWFScriptMessageHandlerHostApiTests.m in Sources */, 334734012669319100DCC49E /* FLTWebViewTests.m in Sources */, + 8FB79B7928209D1300C101D3 /* FWFUserContentControllerHostApiTests.m in Sources */, + 8FB79B6B28204EE500C101D3 /* FWFWebsiteDataStoreHostApiTests.m in Sources */, + 8FB79B8F2820BAB300C101D3 /* FWFScrollViewHostApiTests.m in Sources */, + 8FB79B912820BAC700C101D3 /* FWFUIViewHostApiTests.m in Sources */, 334734022669319400DCC49E /* FLTWKNavigationDelegateTests.m in Sources */, 8FB79B55281B24F600C101D3 /* FWFDataConvertersTests.m in Sources */, + 8FB79B6D2820533B00C101D3 /* FWFWebViewConfigurationHostApiTests.m in Sources */, + 8FB79B832820A39300C101D3 /* FWFNavigationDelegateHostApiTests.m in Sources */, E43693B527512C0F00382F85 /* FLTCookieManagerTests.m in Sources */, + 8FB79B6928204E8700C101D3 /* FWFPreferencesHostApiTests.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; 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 55952373998d..57d90f6c6814 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 @@ -10,7 +10,7 @@ @interface FWFDataConvertersTests : XCTestCase @end @implementation FWFDataConvertersTests -- (void)testFNSURLRequestFromRequestData { +- (void)testFWFNSURLRequestFromRequestData { NSURLRequest *request = FWFNSURLRequestFromRequestData([FWFNSUrlRequestData makeWithUrl:@"https://flutter.dev" httpMethod:@"post" @@ -22,4 +22,25 @@ - (void)testFNSURLRequestFromRequestData { XCTAssertEqualObjects(request.HTTPBody, [NSData data]); XCTAssertEqualObjects(request.allHTTPHeaderFields, @{@"a" : @"header"}); } + +- (void)testFWFNSHTTPCookieFromCookieData { + NSHTTPCookie *cookie = FWFNSHTTPCookieFromCookieData([FWFNSHttpCookieData + makeWithPropertyKeys:@[ [FWFNSHttpCookiePropertyKeyEnumData + makeWithValue:FWFNSHttpCookiePropertyKeyEnumName] ] + propertyValues:@[ @"cookieName" ]]); + XCTAssertEqualObjects(cookie, + [NSHTTPCookie cookieWithProperties:@{NSHTTPCookieName : @"cookieName"}]); +} + +- (void)testFWFWKUserScriptFromScriptData { + WKUserScript *userScript = FWFWKUserScriptFromScriptData([FWFWKUserScriptData + makeWithSource:@"mySource" + injectionTime:[FWFWKUserScriptInjectionTimeEnumData + makeWithValue:FWFWKUserScriptInjectionTimeEnumAtDocumentStart] + isMainFrameOnly:@NO]); + + XCTAssertEqualObjects(userScript.source, @"mySource"); + XCTAssertEqual(userScript.injectionTime, WKUserScriptInjectionTimeAtDocumentStart); + XCTAssertEqual(userScript.isForMainFrameOnly, NO); +} @end diff --git a/packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerTests/FWFHTTPCookieStoreHostApiTests.m b/packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerTests/FWFHTTPCookieStoreHostApiTests.m new file mode 100644 index 000000000000..315640a99247 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerTests/FWFHTTPCookieStoreHostApiTests.m @@ -0,0 +1,55 @@ +// 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 Flutter; +@import XCTest; +@import webview_flutter_wkwebview; + +#import + +@interface FWFHTTPCookieStoreHostApiTests : XCTestCase +@end + +@implementation FWFHTTPCookieStoreHostApiTests +- (void)testCreateFromWebsiteDataStoreWithIdentifier API_AVAILABLE(ios(11.0)) { + FWFInstanceManager *instanceManager = [[FWFInstanceManager alloc] init]; + FWFHTTPCookieStoreHostApiImpl *hostApi = + [[FWFHTTPCookieStoreHostApiImpl alloc] initWithInstanceManager:instanceManager]; + + WKWebsiteDataStore *mockDataStore = OCMClassMock([WKWebsiteDataStore class]); + OCMStub([mockDataStore httpCookieStore]).andReturn(OCMClassMock([WKHTTPCookieStore class])); + [instanceManager addInstance:mockDataStore withIdentifier:0]; + + FlutterError *error; + [hostApi createFromWebsiteDataStoreWithIdentifier:@1 dataStoreIdentifier:@0 error:&error]; + WKHTTPCookieStore *cookieStore = (WKHTTPCookieStore *)[instanceManager instanceForIdentifier:1]; + XCTAssertTrue([cookieStore isKindOfClass:[WKHTTPCookieStore class]]); + XCTAssertNil(error); +} + +- (void)testSetCookie API_AVAILABLE(ios(11.0)) { + WKHTTPCookieStore *mockHttpCookieStore = OCMClassMock([WKHTTPCookieStore class]); + + FWFInstanceManager *instanceManager = [[FWFInstanceManager alloc] init]; + [instanceManager addInstance:mockHttpCookieStore withIdentifier:0]; + + FWFHTTPCookieStoreHostApiImpl *hostApi = + [[FWFHTTPCookieStoreHostApiImpl alloc] initWithInstanceManager:instanceManager]; + + FWFNSHttpCookieData *cookieData = [FWFNSHttpCookieData + makeWithPropertyKeys:@[ [FWFNSHttpCookiePropertyKeyEnumData + makeWithValue:FWFNSHttpCookiePropertyKeyEnumName] ] + propertyValues:@[ @"hello" ]]; + FlutterError *__block blockError; + [hostApi setCookieForStoreWithIdentifier:@0 + cookie:cookieData + completion:^(FlutterError *error) { + blockError = error; + }]; + OCMVerify([mockHttpCookieStore + setCookie:[NSHTTPCookie cookieWithProperties:@{NSHTTPCookieName : @"hello"}] + completionHandler:OCMOCK_ANY]); + XCTAssertNil(blockError); +} +@end diff --git a/packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerTests/FWFNavigationDelegateHostApiTests.m b/packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerTests/FWFNavigationDelegateHostApiTests.m new file mode 100644 index 000000000000..02e473f8b795 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerTests/FWFNavigationDelegateHostApiTests.m @@ -0,0 +1,28 @@ +// 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 Flutter; +@import XCTest; +@import webview_flutter_wkwebview; + +#import + +@interface FWFNavigationDelegateHostApiTests : XCTestCase +@end + +@implementation FWFNavigationDelegateHostApiTests +- (void)testCreateWithIdentifier { + FWFInstanceManager *instanceManager = [[FWFInstanceManager alloc] init]; + FWFNavigationDelegateHostApiImpl *hostApi = + [[FWFNavigationDelegateHostApiImpl alloc] initWithInstanceManager:instanceManager]; + + FlutterError *error; + [hostApi createWithIdentifier:@0 error:&error]; + FWFNavigationDelegate *navigationDelegate = + (FWFNavigationDelegate *)[instanceManager instanceForIdentifier:0]; + + XCTAssertTrue([navigationDelegate conformsToProtocol:@protocol(WKNavigationDelegate)]); + XCTAssertNil(error); +} +@end diff --git a/packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerTests/FWFObjectHostApiTests.m b/packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerTests/FWFObjectHostApiTests.m new file mode 100644 index 000000000000..6886c2600e13 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerTests/FWFObjectHostApiTests.m @@ -0,0 +1,82 @@ +// 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 Flutter; +@import XCTest; +@import webview_flutter_wkwebview; + +#import + +@interface FWFObjectHostApiTests : XCTestCase +@end + +@implementation FWFObjectHostApiTests +- (void)testAddObserver { + NSObject *mockObject = OCMClassMock([NSObject class]); + + FWFInstanceManager *instanceManager = [[FWFInstanceManager alloc] init]; + [instanceManager addInstance:mockObject withIdentifier:0]; + + FWFObjectHostApiImpl *hostApi = + [[FWFObjectHostApiImpl alloc] initWithInstanceManager:instanceManager]; + + NSObject *observerObject = [[NSObject alloc] init]; + [instanceManager addInstance:observerObject withIdentifier:1]; + + FlutterError *error; + [hostApi + addObserverForObjectWithIdentifier:@0 + observerIdentifier:@1 + keyPath:@"myKey" + options:@[ + [FWFNSKeyValueObservingOptionsEnumData + makeWithValue:FWFNSKeyValueObservingOptionsEnumOldValue], + [FWFNSKeyValueObservingOptionsEnumData + makeWithValue:FWFNSKeyValueObservingOptionsEnumNewValue] + ] + error:&error]; + + OCMVerify([mockObject addObserver:observerObject + forKeyPath:@"myKey" + options:(NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew) + context:nil]); + XCTAssertNil(error); +} + +- (void)testRemoveObserver { + NSObject *mockObject = OCMClassMock([NSObject class]); + + FWFInstanceManager *instanceManager = [[FWFInstanceManager alloc] init]; + [instanceManager addInstance:mockObject withIdentifier:0]; + + FWFObjectHostApiImpl *hostApi = + [[FWFObjectHostApiImpl alloc] initWithInstanceManager:instanceManager]; + + NSObject *observerObject = [[NSObject alloc] init]; + [instanceManager addInstance:observerObject withIdentifier:1]; + + FlutterError *error; + [hostApi removeObserverForObjectWithIdentifier:@0 + observerIdentifier:@1 + keyPath:@"myKey" + error:&error]; + OCMVerify([mockObject removeObserver:observerObject forKeyPath:@"myKey"]); + XCTAssertNil(error); +} + +- (void)testDispose { + NSObject *object = [[NSObject alloc] init]; + + FWFInstanceManager *instanceManager = [[FWFInstanceManager alloc] init]; + [instanceManager addInstance:object withIdentifier:0]; + + FWFObjectHostApiImpl *hostApi = + [[FWFObjectHostApiImpl alloc] initWithInstanceManager:instanceManager]; + + FlutterError *error; + [hostApi disposeObjectWithIdentifier:@0 error:&error]; + XCTAssertEqual([instanceManager identifierForInstance:object], NSNotFound); + XCTAssertNil(error); +} +@end diff --git a/packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerTests/FWFPreferencesHostApiTests.m b/packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerTests/FWFPreferencesHostApiTests.m new file mode 100644 index 000000000000..1837a9373930 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerTests/FWFPreferencesHostApiTests.m @@ -0,0 +1,43 @@ +// 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 Flutter; +@import XCTest; +@import webview_flutter_wkwebview; + +#import + +@interface FWFPreferencesHostApiTests : XCTestCase +@end + +@implementation FWFPreferencesHostApiTests +- (void)testCreateFromWebViewConfigurationWithIdentifier { + FWFInstanceManager *instanceManager = [[FWFInstanceManager alloc] init]; + FWFPreferencesHostApiImpl *hostApi = + [[FWFPreferencesHostApiImpl alloc] initWithInstanceManager:instanceManager]; + + [instanceManager addInstance:[[WKWebViewConfiguration alloc] init] withIdentifier:0]; + + FlutterError *error; + [hostApi createFromWebViewConfigurationWithIdentifier:@1 configurationIdentifier:@0 error:&error]; + WKPreferences *preferences = (WKPreferences *)[instanceManager instanceForIdentifier:1]; + XCTAssertTrue([preferences isKindOfClass:[WKPreferences class]]); + XCTAssertNil(error); +} + +- (void)testSetJavaScriptEnabled { + WKPreferences *mockPreferences = OCMClassMock([WKPreferences class]); + + FWFInstanceManager *instanceManager = [[FWFInstanceManager alloc] init]; + [instanceManager addInstance:mockPreferences withIdentifier:0]; + + FWFPreferencesHostApiImpl *hostApi = + [[FWFPreferencesHostApiImpl alloc] initWithInstanceManager:instanceManager]; + + FlutterError *error; + [hostApi setJavaScriptEnabledForPreferencesWithIdentifier:@0 isEnabled:@YES error:&error]; + OCMVerify([mockPreferences setJavaScriptEnabled:YES]); + XCTAssertNil(error); +} +@end diff --git a/packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerTests/FWFScriptMessageHandlerHostApiTests.m b/packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerTests/FWFScriptMessageHandlerHostApiTests.m new file mode 100644 index 000000000000..cb8348fc4702 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerTests/FWFScriptMessageHandlerHostApiTests.m @@ -0,0 +1,29 @@ +// 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 Flutter; +@import XCTest; +@import webview_flutter_wkwebview; + +#import + +@interface FWFScriptMessageHandlerHostApiTests : XCTestCase +@end + +@implementation FWFScriptMessageHandlerHostApiTests +- (void)testCreateWithIdentifier { + FWFInstanceManager *instanceManager = [[FWFInstanceManager alloc] init]; + FWFScriptMessageHandlerHostApiImpl *hostApi = + [[FWFScriptMessageHandlerHostApiImpl alloc] initWithInstanceManager:instanceManager]; + + FlutterError *error; + [hostApi createWithIdentifier:@0 error:&error]; + + FWFScriptMessageHandler *scriptMessageHandler = + (FWFScriptMessageHandler *)[instanceManager instanceForIdentifier:0]; + + XCTAssertTrue([scriptMessageHandler conformsToProtocol:@protocol(WKScriptMessageHandler)]); + XCTAssertNil(error); +} +@end diff --git a/packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerTests/FWFScrollViewHostApiTests.m b/packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerTests/FWFScrollViewHostApiTests.m new file mode 100644 index 000000000000..87d17119e5e7 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerTests/FWFScrollViewHostApiTests.m @@ -0,0 +1,64 @@ +// 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 Flutter; +@import XCTest; +@import webview_flutter_wkwebview; + +#import + +@interface FWFScrollViewHostApiTests : XCTestCase +@end + +@implementation FWFScrollViewHostApiTests +- (void)testGetContentOffset { + UIScrollView *mockScrollView = OCMClassMock([UIScrollView class]); + OCMStub([mockScrollView contentOffset]).andReturn(CGPointMake(1.0, 2.0)); + + FWFInstanceManager *instanceManager = [[FWFInstanceManager alloc] init]; + [instanceManager addInstance:mockScrollView withIdentifier:0]; + + FWFScrollViewHostApiImpl *hostApi = + [[FWFScrollViewHostApiImpl alloc] initWithInstanceManager:instanceManager]; + + FlutterError *error; + NSArray *expectedValue = @[ @1.0, @2.0 ]; + XCTAssertEqualObjects([hostApi contentOffsetForScrollViewWithIdentifier:@0 error:&error], + expectedValue); + XCTAssertNil(error); +} + +- (void)testScrollBy { + UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 500, 500)]; + scrollView.contentOffset = CGPointMake(1, 2); + + FWFInstanceManager *instanceManager = [[FWFInstanceManager alloc] init]; + [instanceManager addInstance:scrollView withIdentifier:0]; + + FWFScrollViewHostApiImpl *hostApi = + [[FWFScrollViewHostApiImpl alloc] initWithInstanceManager:instanceManager]; + + FlutterError *error; + [hostApi scrollByForScrollViewWithIdentifier:@0 x:@1 y:@2 error:&error]; + XCTAssertEqual(scrollView.contentOffset.x, 2); + XCTAssertEqual(scrollView.contentOffset.y, 4); + XCTAssertNil(error); +} + +- (void)testSetContentOffset { + UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 500, 500)]; + + FWFInstanceManager *instanceManager = [[FWFInstanceManager alloc] init]; + [instanceManager addInstance:scrollView withIdentifier:0]; + + FWFScrollViewHostApiImpl *hostApi = + [[FWFScrollViewHostApiImpl alloc] initWithInstanceManager:instanceManager]; + + FlutterError *error; + [hostApi setContentOffsetForScrollViewWithIdentifier:@0 toX:@1 y:@2 error:&error]; + XCTAssertEqual(scrollView.contentOffset.x, 1); + XCTAssertEqual(scrollView.contentOffset.y, 2); + XCTAssertNil(error); +} +@end diff --git a/packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerTests/FWFUIDelegateHostApiTests.m b/packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerTests/FWFUIDelegateHostApiTests.m new file mode 100644 index 000000000000..2f7838be5aa8 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerTests/FWFUIDelegateHostApiTests.m @@ -0,0 +1,27 @@ +// 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 Flutter; +@import XCTest; +@import webview_flutter_wkwebview; + +#import + +@interface FWFUIDelegateHostApiTests : XCTestCase +@end + +@implementation FWFUIDelegateHostApiTests +- (void)testCreateWithIdentifier { + FWFInstanceManager *instanceManager = [[FWFInstanceManager alloc] init]; + FWFUIDelegateHostApiImpl *hostApi = + [[FWFUIDelegateHostApiImpl alloc] initWithInstanceManager:instanceManager]; + + FlutterError *error; + [hostApi createWithIdentifier:@0 error:&error]; + FWFUIDelegate *delegate = (FWFUIDelegate *)[instanceManager instanceForIdentifier:0]; + + XCTAssertTrue([delegate conformsToProtocol:@protocol(WKUIDelegate)]); + XCTAssertNil(error); +} +@end diff --git a/packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerTests/FWFUIViewHostApiTests.m b/packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerTests/FWFUIViewHostApiTests.m new file mode 100644 index 000000000000..8c7c9c9b45b1 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerTests/FWFUIViewHostApiTests.m @@ -0,0 +1,49 @@ +// 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 Flutter; +@import XCTest; +@import webview_flutter_wkwebview; + +#import + +@interface FWFUIViewHostApiTests : XCTestCase +@end + +@implementation FWFUIViewHostApiTests +- (void)testSetBackgroundColor { + UIView *mockUIView = OCMClassMock([UIView class]); + + FWFInstanceManager *instanceManager = [[FWFInstanceManager alloc] init]; + [instanceManager addInstance:mockUIView withIdentifier:0]; + + FWFUIViewHostApiImpl *hostApi = + [[FWFUIViewHostApiImpl alloc] initWithInstanceManager:instanceManager]; + + FlutterError *error; + [hostApi setBackgroundColorForViewWithIdentifier:@0 toValue:@123 error:&error]; + + OCMVerify([mockUIView setBackgroundColor:[UIColor colorWithRed:(123 >> 16 & 0xff) / 255.0 + green:(123 >> 8 & 0xff) / 255.0 + blue:(123 & 0xff) / 255.0 + alpha:(123 >> 24 & 0xff) / 255.0]]); + XCTAssertNil(error); +} + +- (void)testSetOpaque { + UIView *mockUIView = OCMClassMock([UIView class]); + + FWFInstanceManager *instanceManager = [[FWFInstanceManager alloc] init]; + [instanceManager addInstance:mockUIView withIdentifier:0]; + + FWFUIViewHostApiImpl *hostApi = + [[FWFUIViewHostApiImpl alloc] initWithInstanceManager:instanceManager]; + + FlutterError *error; + [hostApi setOpaqueForViewWithIdentifier:@0 isOpaque:@YES error:&error]; + OCMVerify([mockUIView setOpaque:YES]); + XCTAssertNil(error); +} + +@end diff --git a/packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerTests/FWFUserContentControllerHostApiTests.m b/packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerTests/FWFUserContentControllerHostApiTests.m new file mode 100644 index 000000000000..d70341e87890 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerTests/FWFUserContentControllerHostApiTests.m @@ -0,0 +1,127 @@ +// 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 Flutter; +@import XCTest; +@import webview_flutter_wkwebview; + +#import + +@interface FWFUserContentControllerHostApiTests : XCTestCase +@end + +@implementation FWFUserContentControllerHostApiTests +- (void)testCreateFromWebViewConfigurationWithIdentifier { + FWFInstanceManager *instanceManager = [[FWFInstanceManager alloc] init]; + FWFUserContentControllerHostApiImpl *hostApi = + [[FWFUserContentControllerHostApiImpl alloc] initWithInstanceManager:instanceManager]; + + [instanceManager addInstance:[[WKWebViewConfiguration alloc] init] withIdentifier:0]; + + FlutterError *error; + [hostApi createFromWebViewConfigurationWithIdentifier:@1 configurationIdentifier:@0 error:&error]; + WKUserContentController *userContentController = + (WKUserContentController *)[instanceManager instanceForIdentifier:1]; + XCTAssertTrue([userContentController isKindOfClass:[WKUserContentController class]]); + XCTAssertNil(error); +} + +- (void)testAddScriptMessageHandler { + WKUserContentController *mockUserContentController = + OCMClassMock([WKUserContentController class]); + + FWFInstanceManager *instanceManager = [[FWFInstanceManager alloc] init]; + [instanceManager addInstance:mockUserContentController withIdentifier:0]; + + FWFUserContentControllerHostApiImpl *hostApi = + [[FWFUserContentControllerHostApiImpl alloc] initWithInstanceManager:instanceManager]; + + id mockMessageHandler = + OCMProtocolMock(@protocol(WKScriptMessageHandler)); + [instanceManager addInstance:mockMessageHandler withIdentifier:1]; + + FlutterError *error; + [hostApi addScriptMessageHandlerForControllerWithIdentifier:@0 + handlerIdentifier:@1 + ofName:@"apple" + error:&error]; + OCMVerify([mockUserContentController addScriptMessageHandler:mockMessageHandler name:@"apple"]); + XCTAssertNil(error); +} + +- (void)testRemoveScriptMessageHandler { + WKUserContentController *mockUserContentController = + OCMClassMock([WKUserContentController class]); + + FWFInstanceManager *instanceManager = [[FWFInstanceManager alloc] init]; + [instanceManager addInstance:mockUserContentController withIdentifier:0]; + + FWFUserContentControllerHostApiImpl *hostApi = + [[FWFUserContentControllerHostApiImpl alloc] initWithInstanceManager:instanceManager]; + + FlutterError *error; + [hostApi removeScriptMessageHandlerForControllerWithIdentifier:@0 name:@"apple" error:&error]; + OCMVerify([mockUserContentController removeScriptMessageHandlerForName:@"apple"]); + XCTAssertNil(error); +} + +- (void)testRemoveAllScriptMessageHandlers API_AVAILABLE(ios(14.0)) { + WKUserContentController *mockUserContentController = + OCMClassMock([WKUserContentController class]); + + FWFInstanceManager *instanceManager = [[FWFInstanceManager alloc] init]; + [instanceManager addInstance:mockUserContentController withIdentifier:0]; + + FWFUserContentControllerHostApiImpl *hostApi = + [[FWFUserContentControllerHostApiImpl alloc] initWithInstanceManager:instanceManager]; + + FlutterError *error; + [hostApi removeAllScriptMessageHandlersForControllerWithIdentifier:@0 error:&error]; + OCMVerify([mockUserContentController removeAllScriptMessageHandlers]); + XCTAssertNil(error); +} + +- (void)testAddUserScript { + WKUserContentController *mockUserContentController = + OCMClassMock([WKUserContentController class]); + + FWFInstanceManager *instanceManager = [[FWFInstanceManager alloc] init]; + [instanceManager addInstance:mockUserContentController withIdentifier:0]; + + FWFUserContentControllerHostApiImpl *hostApi = + [[FWFUserContentControllerHostApiImpl alloc] initWithInstanceManager:instanceManager]; + + FlutterError *error; + [hostApi + addUserScriptForControllerWithIdentifier:@0 + userScript: + [FWFWKUserScriptData + makeWithSource:@"runAScript" + injectionTime: + [FWFWKUserScriptInjectionTimeEnumData + makeWithValue: + FWFWKUserScriptInjectionTimeEnumAtDocumentEnd] + isMainFrameOnly:@YES] + error:&error]; + + OCMVerify([mockUserContentController addUserScript:[OCMArg isKindOfClass:[WKUserScript class]]]); + XCTAssertNil(error); +} + +- (void)testRemoveAllUserScripts { + WKUserContentController *mockUserContentController = + OCMClassMock([WKUserContentController class]); + + FWFInstanceManager *instanceManager = [[FWFInstanceManager alloc] init]; + [instanceManager addInstance:mockUserContentController withIdentifier:0]; + + FWFUserContentControllerHostApiImpl *hostApi = + [[FWFUserContentControllerHostApiImpl alloc] initWithInstanceManager:instanceManager]; + + FlutterError *error; + [hostApi removeAllUserScriptsForControllerWithIdentifier:@0 error:&error]; + OCMVerify([mockUserContentController removeAllUserScripts]); + XCTAssertNil(error); +} +@end diff --git a/packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerTests/FWFWebViewConfigurationHostApiTests.m b/packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerTests/FWFWebViewConfigurationHostApiTests.m new file mode 100644 index 000000000000..dab10799891b --- /dev/null +++ b/packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerTests/FWFWebViewConfigurationHostApiTests.m @@ -0,0 +1,88 @@ +// 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 Flutter; +@import XCTest; +@import webview_flutter_wkwebview; + +#import + +@interface FWFWebViewConfigurationHostApiTests : XCTestCase +@end + +@implementation FWFWebViewConfigurationHostApiTests +- (void)testCreateWithIdentifier { + FWFInstanceManager *instanceManager = [[FWFInstanceManager alloc] init]; + FWFWebViewConfigurationHostApiImpl *hostApi = + [[FWFWebViewConfigurationHostApiImpl alloc] initWithInstanceManager:instanceManager]; + + FlutterError *error; + [hostApi createWithIdentifier:@0 error:&error]; + WKWebViewConfiguration *configuration = + (WKWebViewConfiguration *)[instanceManager instanceForIdentifier:0]; + XCTAssertTrue([configuration isKindOfClass:[WKWebViewConfiguration class]]); + XCTAssertNil(error); +} + +- (void)testCreateFromWebViewWithIdentifier { + FWFInstanceManager *instanceManager = [[FWFInstanceManager alloc] init]; + FWFWebViewConfigurationHostApiImpl *hostApi = + [[FWFWebViewConfigurationHostApiImpl alloc] initWithInstanceManager:instanceManager]; + + WKWebView *mockWebView = OCMClassMock([WKWebView class]); + OCMStub([mockWebView configuration]).andReturn(OCMClassMock([WKWebViewConfiguration class])); + [instanceManager addInstance:mockWebView withIdentifier:0]; + + FlutterError *error; + [hostApi createFromWebViewWithIdentifier:@1 webViewIdentifier:@0 error:&error]; + WKWebViewConfiguration *configuration = + (WKWebViewConfiguration *)[instanceManager instanceForIdentifier:1]; + XCTAssertTrue([configuration isKindOfClass:[WKWebViewConfiguration class]]); + XCTAssertNil(error); +} + +- (void)testSetAllowsInlineMediaPlayback { + WKWebViewConfiguration *mockWebViewConfiguration = OCMClassMock([WKWebViewConfiguration class]); + + FWFInstanceManager *instanceManager = [[FWFInstanceManager alloc] init]; + [instanceManager addInstance:mockWebViewConfiguration withIdentifier:0]; + + FWFWebViewConfigurationHostApiImpl *hostApi = + [[FWFWebViewConfigurationHostApiImpl alloc] initWithInstanceManager:instanceManager]; + + FlutterError *error; + [hostApi setAllowsInlineMediaPlaybackForConfigurationWithIdentifier:@0 + isAllowed:@NO + error:&error]; + OCMVerify([mockWebViewConfiguration setAllowsInlineMediaPlayback:NO]); + XCTAssertNil(error); +} + +- (void)testSetMediaTypesRequiringUserActionForPlayback { + WKWebViewConfiguration *mockWebViewConfiguration = OCMClassMock([WKWebViewConfiguration class]); + + FWFInstanceManager *instanceManager = [[FWFInstanceManager alloc] init]; + [instanceManager addInstance:mockWebViewConfiguration withIdentifier:0]; + + FWFWebViewConfigurationHostApiImpl *hostApi = + [[FWFWebViewConfigurationHostApiImpl alloc] initWithInstanceManager:instanceManager]; + + FlutterError *error; + [hostApi + setMediaTypesRequiresUserActionForConfigurationWithIdentifier:@0 + forTypes:@[ + [FWFWKAudiovisualMediaTypeEnumData + makeWithValue: + FWFWKAudiovisualMediaTypeEnumAudio], + [FWFWKAudiovisualMediaTypeEnumData + makeWithValue: + FWFWKAudiovisualMediaTypeEnumVideo] + ] + error:&error]; + OCMVerify([mockWebViewConfiguration + setMediaTypesRequiringUserActionForPlayback:(WKAudiovisualMediaTypeAudio | + WKAudiovisualMediaTypeVideo)]); + XCTAssertNil(error); +} +@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 dc0c1ce593d2..87960c07ee5e 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 @@ -12,6 +12,20 @@ @interface FWFWebViewHostApiTests : XCTestCase @end @implementation FWFWebViewHostApiTests +- (void)testCreateWithIdentifier { + FWFInstanceManager *instanceManager = [[FWFInstanceManager alloc] init]; + FWFWebViewHostApiImpl *hostApi = + [[FWFWebViewHostApiImpl alloc] initWithInstanceManager:instanceManager]; + + [instanceManager addInstance:[[WKWebViewConfiguration alloc] init] withIdentifier:0]; + + FlutterError *error; + [hostApi createWithIdentifier:@1 configurationIdentifier:@0 error:&error]; + WKWebView *webView = (WKWebView *)[instanceManager instanceForIdentifier:1]; + XCTAssertTrue([webView isKindOfClass:[WKWebView class]]); + XCTAssertNil(error); +} + - (void)testLoadRequest { FWFWebView *mockWebView = OCMClassMock([FWFWebView class]); diff --git a/packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerTests/FWFWebsiteDataStoreHostApiTests.m b/packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerTests/FWFWebsiteDataStoreHostApiTests.m new file mode 100644 index 000000000000..c754f78551b9 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerTests/FWFWebsiteDataStoreHostApiTests.m @@ -0,0 +1,75 @@ +// 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 Flutter; +@import XCTest; +@import webview_flutter_wkwebview; + +#import + +@interface FWFWebsiteDataStoreHostApiTests : XCTestCase +@end + +@implementation FWFWebsiteDataStoreHostApiTests +- (void)testCreateFromWebViewConfigurationWithIdentifier { + FWFInstanceManager *instanceManager = [[FWFInstanceManager alloc] init]; + FWFWebsiteDataStoreHostApiImpl *hostApi = + [[FWFWebsiteDataStoreHostApiImpl alloc] initWithInstanceManager:instanceManager]; + + [instanceManager addInstance:[[WKWebViewConfiguration alloc] init] withIdentifier:0]; + + FlutterError *error; + [hostApi createFromWebViewConfigurationWithIdentifier:@1 configurationIdentifier:@0 error:&error]; + WKWebsiteDataStore *dataStore = (WKWebsiteDataStore *)[instanceManager instanceForIdentifier:1]; + XCTAssertTrue([dataStore isKindOfClass:[WKWebsiteDataStore class]]); + XCTAssertNil(error); +} + +- (void)testCreateDefaultDataStoreWithIdentifier { + FWFInstanceManager *instanceManager = [[FWFInstanceManager alloc] init]; + FWFWebsiteDataStoreHostApiImpl *hostApi = + [[FWFWebsiteDataStoreHostApiImpl alloc] initWithInstanceManager:instanceManager]; + + FlutterError *error; + [hostApi createDefaultDataStoreWithIdentifier:@0 error:&error]; + WKWebsiteDataStore *dataStore = (WKWebsiteDataStore *)[instanceManager instanceForIdentifier:0]; + XCTAssertEqualObjects(dataStore, [WKWebsiteDataStore defaultDataStore]); + XCTAssertNil(error); +} + +- (void)testRemoveDataOfTypes { + WKWebsiteDataStore *mockWebsiteDataStore = OCMClassMock([WKWebsiteDataStore class]); + + WKWebsiteDataRecord *mockDataRecord = OCMClassMock([WKWebsiteDataRecord class]); + OCMStub([mockWebsiteDataStore + fetchDataRecordsOfTypes:[NSSet setWithObject:WKWebsiteDataTypeLocalStorage] + completionHandler:([OCMArg invokeBlockWithArgs:@[ mockDataRecord ], nil])]); + + OCMStub([mockWebsiteDataStore + removeDataOfTypes:[NSSet setWithObject:WKWebsiteDataTypeLocalStorage] + modifiedSince:[NSDate dateWithTimeIntervalSince1970:45.0] + completionHandler:([OCMArg invokeBlock])]); + + FWFInstanceManager *instanceManager = [[FWFInstanceManager alloc] init]; + [instanceManager addInstance:mockWebsiteDataStore withIdentifier:0]; + + FWFWebsiteDataStoreHostApiImpl *hostApi = + [[FWFWebsiteDataStoreHostApiImpl alloc] initWithInstanceManager:instanceManager]; + + NSNumber __block *returnValue; + FlutterError *__block blockError; + [hostApi removeDataFromDataStoreWithIdentifier:@0 + ofTypes:@[ + [FWFWKWebsiteDataTypeEnumData + makeWithValue:FWFWKWebsiteDataTypeEnumLocalStorage] + ] + modifiedSince:@45.0 + completion:^(NSNumber *result, FlutterError *error) { + returnValue = result; + blockError = error; + }]; + XCTAssertEqualObjects(returnValue, @YES); + XCTAssertNil(blockError); +} +@end diff --git a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFDataConverters.h b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFDataConverters.h index e9dbf2d9efa7..4cf24c67ac95 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFDataConverters.h +++ b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFDataConverters.h @@ -4,6 +4,8 @@ #import "FWFGeneratedWebKitApis.h" +#import + NS_ASSUME_NONNULL_BEGIN /** @@ -13,7 +15,74 @@ NS_ASSUME_NONNULL_BEGIN * * @return An NSURLRequest or nil if data could not be converted. */ -extern NSURLRequest* _Nullable FWFNSURLRequestFromRequestData( - FWFNSUrlRequestData* data); +extern NSURLRequest *_Nullable FWFNSURLRequestFromRequestData(FWFNSUrlRequestData *data); + +/** + * Converts an FWFNSHttpCookieData to an NSHTTPCookie. + * + * @param data The data object containing information to create an NSHTTPCookie. + * + * @return An NSHTTPCookie or nil if data could not be converted. + */ +extern NSHTTPCookie *_Nullable FWFNSHTTPCookieFromCookieData(FWFNSHttpCookieData *data); + +/** + * Converts an FWFNSKeyValueObservingOptionsEnumData to an NSKeyValueObservingOptions. + * + * @param data The data object containing information to create an NSKeyValueObservingOptions. + * + * @return An NSKeyValueObservingOptions or -1 if data could not be converted. + */ +extern NSKeyValueObservingOptions FWFNSKeyValueObservingOptionsFromEnumData( + FWFNSKeyValueObservingOptionsEnumData *data); + +/** + * Converts an FWFNSHTTPCookiePropertyKeyEnumData to an NSHTTPCookiePropertyKey. + * + * @param data The data object containing information to create an NSHTTPCookiePropertyKey. + * + * @return An NSHttpCookiePropertyKey or nil if data could not be converted. + */ +extern NSHTTPCookiePropertyKey _Nullable FWFNSHTTPCookiePropertyKeyFromEnumData( + FWFNSHttpCookiePropertyKeyEnumData *data); + +/** + * Converts a WKUserScriptData to a WKUserScript. + * + * @param data The data object containing information to create a WKUserScript. + * + * @return A WKUserScript or nil if data could not be converted. + */ +extern WKUserScript *FWFWKUserScriptFromScriptData(FWFWKUserScriptData *data); + +/** + * Converts an FWFWKUserScriptInjectionTimeEnumData to a WKUserScriptInjectionTime. + * + * @param data The data object containing information to create a WKUserScriptInjectionTime. + * + * @return A WKUserScriptInjectionTime or -1 if data could not be converted. + */ +extern WKUserScriptInjectionTime FWFWKUserScriptInjectionTimeFromEnumData( + FWFWKUserScriptInjectionTimeEnumData *data); + +/** + * Converts an FWFWKAudiovisualMediaTypeEnumData to a WKAudiovisualMediaTypes. + * + * @param data The data object containing information to create a WKAudiovisualMediaTypes. + * + * @return A WKAudiovisualMediaType or -1 if data could not be converted. + */ +API_AVAILABLE(ios(10.0)) +extern WKAudiovisualMediaTypes FWFWKAudiovisualMediaTypeFromEnumData( + FWFWKAudiovisualMediaTypeEnumData *data); + +/** + * Converts an FWFWKWebsiteDataTypeEnumData to a WKWebsiteDataType. + * + * @param data The data object containing information to create a WKWebsiteDataType. + * + * @return A WKWebsiteDataType or nil if data could not be converted. + */ +extern NSString *_Nullable FWFWKWebsiteDataTypeFromEnumData(FWFWKWebsiteDataTypeEnumData *data); NS_ASSUME_NONNULL_END 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 1945bc3354f3..a06b3d79b38c 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFDataConverters.m +++ b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFDataConverters.m @@ -23,3 +23,133 @@ return request; } + +extern NSHTTPCookie *_Nullable FWFNSHTTPCookieFromCookieData(FWFNSHttpCookieData *data) { + NSMutableDictionary *properties = [NSMutableDictionary dictionary]; + for (int i = 0; i < data.propertyKeys.count; i++) { + NSHTTPCookiePropertyKey cookieKey = + FWFNSHTTPCookiePropertyKeyFromEnumData(data.propertyKeys[i]); + if (!cookieKey) { + // Some keys aren't supported on all versions, so this ignores keys + // that require a higher version or are unsupported. + continue; + } + [properties setObject:data.propertyValues[i] forKey:cookieKey]; + } + return [NSHTTPCookie cookieWithProperties:properties]; +} + +NSKeyValueObservingOptions FWFNSKeyValueObservingOptionsFromEnumData( + FWFNSKeyValueObservingOptionsEnumData *data) { + switch (data.value) { + case FWFNSKeyValueObservingOptionsEnumNewValue: + return NSKeyValueObservingOptionNew; + case FWFNSKeyValueObservingOptionsEnumOldValue: + return NSKeyValueObservingOptionOld; + case FWFNSKeyValueObservingOptionsEnumInitialValue: + return NSKeyValueObservingOptionInitial; + case FWFNSKeyValueObservingOptionsEnumPriorNotification: + return NSKeyValueObservingOptionPrior; + } + + return -1; +} + +NSHTTPCookiePropertyKey _Nullable FWFNSHTTPCookiePropertyKeyFromEnumData( + FWFNSHttpCookiePropertyKeyEnumData *data) { + switch (data.value) { + case FWFNSHttpCookiePropertyKeyEnumComment: + return NSHTTPCookieComment; + case FWFNSHttpCookiePropertyKeyEnumCommentUrl: + return NSHTTPCookieCommentURL; + case FWFNSHttpCookiePropertyKeyEnumDiscard: + return NSHTTPCookieDiscard; + case FWFNSHttpCookiePropertyKeyEnumDomain: + return NSHTTPCookieDomain; + case FWFNSHttpCookiePropertyKeyEnumExpires: + return NSHTTPCookieExpires; + case FWFNSHttpCookiePropertyKeyEnumMaximumAge: + return NSHTTPCookieMaximumAge; + case FWFNSHttpCookiePropertyKeyEnumName: + return NSHTTPCookieName; + case FWFNSHttpCookiePropertyKeyEnumOriginUrl: + return NSHTTPCookieOriginURL; + case FWFNSHttpCookiePropertyKeyEnumPath: + return NSHTTPCookiePath; + case FWFNSHttpCookiePropertyKeyEnumPort: + return NSHTTPCookiePort; + case FWFNSHttpCookiePropertyKeyEnumSameSitePolicy: + if (@available(iOS 13.0, *)) { + return NSHTTPCookieSameSitePolicy; + } else { + return nil; + } + case FWFNSHttpCookiePropertyKeyEnumSecure: + return NSHTTPCookieSecure; + case FWFNSHttpCookiePropertyKeyEnumValue: + return NSHTTPCookieValue; + case FWFNSHttpCookiePropertyKeyEnumVersion: + return NSHTTPCookieVersion; + } + + return nil; +} + +extern WKUserScript *FWFWKUserScriptFromScriptData(FWFWKUserScriptData *data) { + return [[WKUserScript alloc] + initWithSource:data.source + injectionTime:FWFWKUserScriptInjectionTimeFromEnumData(data.injectionTime) + forMainFrameOnly:data.isMainFrameOnly.boolValue]; +} + +WKUserScriptInjectionTime FWFWKUserScriptInjectionTimeFromEnumData( + FWFWKUserScriptInjectionTimeEnumData *data) { + switch (data.value) { + case FWFWKUserScriptInjectionTimeEnumAtDocumentStart: + return WKUserScriptInjectionTimeAtDocumentStart; + case FWFWKUserScriptInjectionTimeEnumAtDocumentEnd: + return WKUserScriptInjectionTimeAtDocumentEnd; + } + + return -1; +} + +API_AVAILABLE(ios(10.0)) +WKAudiovisualMediaTypes FWFWKAudiovisualMediaTypeFromEnumData( + FWFWKAudiovisualMediaTypeEnumData *data) { + switch (data.value) { + case FWFWKAudiovisualMediaTypeEnumNone: + return WKAudiovisualMediaTypeNone; + case FWFWKAudiovisualMediaTypeEnumAudio: + return WKAudiovisualMediaTypeAudio; + case FWFWKAudiovisualMediaTypeEnumVideo: + return WKAudiovisualMediaTypeVideo; + case FWFWKAudiovisualMediaTypeEnumAll: + return WKAudiovisualMediaTypeAll; + } + + return -1; +} + +NSString *_Nullable FWFWKWebsiteDataTypeFromEnumData(FWFWKWebsiteDataTypeEnumData *data) { + switch (data.value) { + case FWFWKWebsiteDataTypeEnumCookies: + return WKWebsiteDataTypeCookies; + case FWFWKWebsiteDataTypeEnumMemoryCache: + return WKWebsiteDataTypeMemoryCache; + case FWFWKWebsiteDataTypeEnumDiskCache: + return WKWebsiteDataTypeDiskCache; + case FWFWKWebsiteDataTypeEnumOfflineWebApplicationCache: + return WKWebsiteDataTypeOfflineWebApplicationCache; + case FWFWKWebsiteDataTypeEnumLocalStorage: + return WKWebsiteDataTypeLocalStorage; + case FWFWKWebsiteDataTypeEnumSessionStorage: + return WKWebsiteDataTypeSessionStorage; + case FWFWKWebsiteDataTypeEnumWebSQLDatabases: + return WKWebsiteDataTypeWebSQLDatabases; + case FWFWKWebsiteDataTypeEnumIndexedDBDatabases: + return WKWebsiteDataTypeIndexedDBDatabases; + } + + return nil; +} 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 5306b300fc03..7d2bd44050ea 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFGeneratedWebKitApis.h +++ b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFGeneratedWebKitApis.h @@ -45,15 +45,15 @@ typedef NS_ENUM(NSUInteger, FWFWKAudiovisualMediaTypeEnum) { FWFWKAudiovisualMediaTypeEnumAll = 3, }; -typedef NS_ENUM(NSUInteger, FWFWKWebsiteDataTypesEnum) { - FWFWKWebsiteDataTypesEnumCookies = 0, - FWFWKWebsiteDataTypesEnumMemoryCache = 1, - FWFWKWebsiteDataTypesEnumDiskCache = 2, - FWFWKWebsiteDataTypesEnumOfflineWebApplicationCache = 3, - FWFWKWebsiteDataTypesEnumLocalStroage = 4, - FWFWKWebsiteDataTypesEnumSessionStorage = 5, - FWFWKWebsiteDataTypesEnumSqlDatabases = 6, - FWFWKWebsiteDataTypesEnumIndexedDBDatabases = 7, +typedef NS_ENUM(NSUInteger, FWFWKWebsiteDataTypeEnum) { + FWFWKWebsiteDataTypeEnumCookies = 0, + FWFWKWebsiteDataTypeEnumMemoryCache = 1, + FWFWKWebsiteDataTypeEnumDiskCache = 2, + FWFWKWebsiteDataTypeEnumOfflineWebApplicationCache = 3, + FWFWKWebsiteDataTypeEnumLocalStorage = 4, + FWFWKWebsiteDataTypeEnumSessionStorage = 5, + FWFWKWebsiteDataTypeEnumWebSQLDatabases = 6, + FWFWKWebsiteDataTypeEnumIndexedDBDatabases = 7, }; typedef NS_ENUM(NSUInteger, FWFWKNavigationActionPolicyEnum) { @@ -81,33 +81,43 @@ typedef NS_ENUM(NSUInteger, FWFNSHttpCookiePropertyKeyEnum) { @class FWFNSKeyValueObservingOptionsEnumData; @class FWFWKUserScriptInjectionTimeEnumData; @class FWFWKAudiovisualMediaTypeEnumData; -@class FWFWKWebsiteDataTypesEnumData; +@class FWFWKWebsiteDataTypeEnumData; @class FWFNSHttpCookiePropertyKeyEnumData; @class FWFNSUrlRequestData; @class FWFWKUserScriptData; @class FWFNSHttpCookieData; @interface FWFNSKeyValueObservingOptionsEnumData : NSObject +/// `init` unavailable to enforce nonnull fields, see the `make` class method. +- (instancetype)init NS_UNAVAILABLE; + (instancetype)makeWithValue:(FWFNSKeyValueObservingOptionsEnum)value; @property(nonatomic, assign) FWFNSKeyValueObservingOptionsEnum value; @end @interface FWFWKUserScriptInjectionTimeEnumData : NSObject +/// `init` unavailable to enforce nonnull fields, see the `make` class method. +- (instancetype)init NS_UNAVAILABLE; + (instancetype)makeWithValue:(FWFWKUserScriptInjectionTimeEnum)value; @property(nonatomic, assign) FWFWKUserScriptInjectionTimeEnum value; @end @interface FWFWKAudiovisualMediaTypeEnumData : NSObject +/// `init` unavailable to enforce nonnull fields, see the `make` class method. +- (instancetype)init NS_UNAVAILABLE; + (instancetype)makeWithValue:(FWFWKAudiovisualMediaTypeEnum)value; @property(nonatomic, assign) FWFWKAudiovisualMediaTypeEnum value; @end -@interface FWFWKWebsiteDataTypesEnumData : NSObject -+ (instancetype)makeWithValue:(FWFWKWebsiteDataTypesEnum)value; -@property(nonatomic, assign) FWFWKWebsiteDataTypesEnum value; +@interface FWFWKWebsiteDataTypeEnumData : NSObject +/// `init` unavailable to enforce nonnull fields, see the `make` class method. +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)makeWithValue:(FWFWKWebsiteDataTypeEnum)value; +@property(nonatomic, assign) FWFWKWebsiteDataTypeEnum value; @end @interface FWFNSHttpCookiePropertyKeyEnumData : NSObject +/// `init` unavailable to enforce nonnull fields, see the `make` class method. +- (instancetype)init NS_UNAVAILABLE; + (instancetype)makeWithValue:(FWFNSHttpCookiePropertyKeyEnum)value; @property(nonatomic, assign) FWFNSHttpCookiePropertyKeyEnum value; @end @@ -139,24 +149,24 @@ typedef NS_ENUM(NSUInteger, FWFNSHttpCookiePropertyKeyEnum) { @interface FWFNSHttpCookieData : NSObject /// `init` unavailable to enforce nonnull fields, see the `make` class method. - (instancetype)init NS_UNAVAILABLE; -+ (instancetype)makeWithProperties: - (NSDictionary *)properties; -@property(nonatomic, strong) - NSDictionary *properties; ++ (instancetype)makeWithPropertyKeys:(NSArray *)propertyKeys + propertyValues:(NSArray *)propertyValues; +@property(nonatomic, strong) NSArray *propertyKeys; +@property(nonatomic, strong) NSArray *propertyValues; @end /// The codec used by FWFWKWebsiteDataStoreHostApi. NSObject *FWFWKWebsiteDataStoreHostApiGetCodec(void); @protocol FWFWKWebsiteDataStoreHostApi -- (void)createDataStoreFromConfigurationWithIdentifier:(NSNumber *)instanceId - configurationIdentifier:(NSNumber *)configurationInstanceId - error:(FlutterError *_Nullable *_Nonnull)error; +- (void)createFromWebViewConfigurationWithIdentifier:(NSNumber *)instanceId + configurationIdentifier:(NSNumber *)configurationInstanceId + error:(FlutterError *_Nullable *_Nonnull)error; - (void)createDefaultDataStoreWithIdentifier:(NSNumber *)instanceId error:(FlutterError *_Nullable *_Nonnull)error; - (void)removeDataFromDataStoreWithIdentifier:(NSNumber *)instanceId - ofTypes:(NSArray *)dataTypes - secondsModifiedSinceEpoch:(NSNumber *)secondsModifiedSinceEpoch + ofTypes:(NSArray *)dataTypes + modifiedSince:(NSNumber *)modificationTimeInSecondsSinceEpoch completion:(void (^)(NSNumber *_Nullable, FlutterError *_Nullable))completion; @end @@ -169,10 +179,6 @@ extern void FWFWKWebsiteDataStoreHostApiSetup( NSObject *FWFUIViewHostApiGetCodec(void); @protocol FWFUIViewHostApi -/// @return `nil` only when `error != nil`. -- (nullable NSArray *) - contentOffsetForViewWithIdentifier:(NSNumber *)instanceId - error:(FlutterError *_Nullable *_Nonnull)error; - (void)setBackgroundColorForViewWithIdentifier:(NSNumber *)instanceId toValue:(nullable NSNumber *)value error:(FlutterError *_Nullable *_Nonnull)error; @@ -196,7 +202,7 @@ NSObject *FWFUIScrollViewHostApiGetCodec(void); contentOffsetForScrollViewWithIdentifier:(NSNumber *)instanceId error:(FlutterError *_Nullable *_Nonnull)error; - (void)scrollByForScrollViewWithIdentifier:(NSNumber *)instanceId - toX:(NSNumber *)x + x:(NSNumber *)x y:(NSNumber *)y error:(FlutterError *_Nullable *_Nonnull)error; - (void)setContentOffsetForScrollViewWithIdentifier:(NSNumber *)instanceId @@ -217,7 +223,7 @@ NSObject *FWFWKWebViewConfigurationHostApiGetCodec(void); webViewIdentifier:(NSNumber *)webViewInstanceId error:(FlutterError *_Nullable *_Nonnull)error; - (void)setAllowsInlineMediaPlaybackForConfigurationWithIdentifier:(NSNumber *)instanceId - isAlowed:(NSNumber *)allow + isAllowed:(NSNumber *)allow error: (FlutterError *_Nullable *_Nonnull) error; @@ -270,9 +276,9 @@ extern void FWFWKUserContentControllerHostApiSetup( NSObject *FWFWKPreferencesHostApiGetCodec(void); @protocol FWFWKPreferencesHostApi -- (void)createFromWebViewConfiguration:(NSNumber *)instanceId - configurationIdentifier:(NSNumber *)configurationInstanceId - error:(FlutterError *_Nullable *_Nonnull)error; +- (void)createFromWebViewConfigurationWithIdentifier:(NSNumber *)instanceId + configurationIdentifier:(NSNumber *)configurationInstanceId + error:(FlutterError *_Nullable *_Nonnull)error; - (void)setJavaScriptEnabledForPreferencesWithIdentifier:(NSNumber *)instanceId isEnabled:(NSNumber *)enabled error:(FlutterError *_Nullable *_Nonnull)error; @@ -428,7 +434,7 @@ NSObject *FWFWKHttpCookieStoreHostApiGetCodec(void); error:(FlutterError *_Nullable *_Nonnull)error; - (void)setCookieForStoreWithIdentifier:(NSNumber *)instanceId cookie:(FWFNSHttpCookieData *)cookie - error:(FlutterError *_Nullable *_Nonnull)error; + completion:(void (^)(FlutterError *_Nullable))completion; @end extern void FWFWKHttpCookieStoreHostApiSetup(id binaryMessenger, 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 070b3c5cc033..aaeccc5cc1b0 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFGeneratedWebKitApis.m +++ b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFGeneratedWebKitApis.m @@ -45,8 +45,8 @@ @interface FWFWKAudiovisualMediaTypeEnumData () + (FWFWKAudiovisualMediaTypeEnumData *)fromMap:(NSDictionary *)dict; - (NSDictionary *)toMap; @end -@interface FWFWKWebsiteDataTypesEnumData () -+ (FWFWKWebsiteDataTypesEnumData *)fromMap:(NSDictionary *)dict; +@interface FWFWKWebsiteDataTypeEnumData () ++ (FWFWKWebsiteDataTypeEnumData *)fromMap:(NSDictionary *)dict; - (NSDictionary *)toMap; @end @interface FWFNSHttpCookiePropertyKeyEnumData () @@ -120,14 +120,14 @@ - (NSDictionary *)toMap { } @end -@implementation FWFWKWebsiteDataTypesEnumData -+ (instancetype)makeWithValue:(FWFWKWebsiteDataTypesEnum)value { - FWFWKWebsiteDataTypesEnumData *pigeonResult = [[FWFWKWebsiteDataTypesEnumData alloc] init]; +@implementation FWFWKWebsiteDataTypeEnumData ++ (instancetype)makeWithValue:(FWFWKWebsiteDataTypeEnum)value { + FWFWKWebsiteDataTypeEnumData *pigeonResult = [[FWFWKWebsiteDataTypeEnumData alloc] init]; pigeonResult.value = value; return pigeonResult; } -+ (FWFWKWebsiteDataTypesEnumData *)fromMap:(NSDictionary *)dict { - FWFWKWebsiteDataTypesEnumData *pigeonResult = [[FWFWKWebsiteDataTypesEnumData alloc] init]; ++ (FWFWKWebsiteDataTypeEnumData *)fromMap:(NSDictionary *)dict { + FWFWKWebsiteDataTypeEnumData *pigeonResult = [[FWFWKWebsiteDataTypeEnumData alloc] init]; pigeonResult.value = [GetNullableObject(dict, @"value") integerValue]; return pigeonResult; } @@ -220,22 +220,27 @@ - (NSDictionary *)toMap { @end @implementation FWFNSHttpCookieData -+ (instancetype)makeWithProperties: - (NSDictionary *)properties { ++ (instancetype)makeWithPropertyKeys:(NSArray *)propertyKeys + propertyValues:(NSArray *)propertyValues { FWFNSHttpCookieData *pigeonResult = [[FWFNSHttpCookieData alloc] init]; - pigeonResult.properties = properties; + pigeonResult.propertyKeys = propertyKeys; + pigeonResult.propertyValues = propertyValues; return pigeonResult; } + (FWFNSHttpCookieData *)fromMap:(NSDictionary *)dict { FWFNSHttpCookieData *pigeonResult = [[FWFNSHttpCookieData alloc] init]; - pigeonResult.properties = GetNullableObject(dict, @"properties"); - NSAssert(pigeonResult.properties != nil, @""); + pigeonResult.propertyKeys = GetNullableObject(dict, @"propertyKeys"); + NSAssert(pigeonResult.propertyKeys != nil, @""); + pigeonResult.propertyValues = GetNullableObject(dict, @"propertyValues"); + NSAssert(pigeonResult.propertyValues != nil, @""); return pigeonResult; } - (NSDictionary *)toMap { return [NSDictionary - dictionaryWithObjectsAndKeys:(self.properties ? self.properties : [NSNull null]), - @"properties", nil]; + dictionaryWithObjectsAndKeys:(self.propertyKeys ? self.propertyKeys : [NSNull null]), + @"propertyKeys", + (self.propertyValues ? self.propertyValues : [NSNull null]), + @"propertyValues", nil]; } @end @@ -245,7 +250,7 @@ @implementation FWFWKWebsiteDataStoreHostApiCodecReader - (nullable id)readValueOfType:(UInt8)type { switch (type) { case 128: - return [FWFWKWebsiteDataTypesEnumData fromMap:[self readValue]]; + return [FWFWKWebsiteDataTypeEnumData fromMap:[self readValue]]; default: return [super readValueOfType:type]; @@ -257,7 +262,7 @@ @interface FWFWKWebsiteDataStoreHostApiCodecWriter : FlutterStandardWriter @end @implementation FWFWKWebsiteDataStoreHostApiCodecWriter - (void)writeValue:(id)value { - if ([value isKindOfClass:[FWFWKWebsiteDataTypesEnumData class]]) { + if ([value isKindOfClass:[FWFWKWebsiteDataTypeEnumData class]]) { [self writeByte:128]; [self writeValue:[value toMap]]; } else { @@ -298,20 +303,19 @@ void FWFWKWebsiteDataStoreHostApiSetup(id binaryMessenge codec:FWFWKWebsiteDataStoreHostApiGetCodec()]; if (api) { NSCAssert( - [api respondsToSelector:@selector(createDataStoreFromConfigurationWithIdentifier: - configurationIdentifier:error:)], + [api respondsToSelector:@selector(createFromWebViewConfigurationWithIdentifier: + configurationIdentifier:error:)], @"FWFWKWebsiteDataStoreHostApi api (%@) doesn't respond to " - @"@selector(createDataStoreFromConfigurationWithIdentifier:configurationIdentifier:error:" - @")", + @"@selector(createFromWebViewConfigurationWithIdentifier:configurationIdentifier:error:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { NSArray *args = message; NSNumber *arg_instanceId = GetNullableObjectAtIndex(args, 0); NSNumber *arg_configurationInstanceId = GetNullableObjectAtIndex(args, 1); FlutterError *error; - [api createDataStoreFromConfigurationWithIdentifier:arg_instanceId - configurationIdentifier:arg_configurationInstanceId - error:&error]; + [api createFromWebViewConfigurationWithIdentifier:arg_instanceId + configurationIdentifier:arg_configurationInstanceId + error:&error]; callback(wrapResult(nil, error)); }]; } else { @@ -345,21 +349,20 @@ void FWFWKWebsiteDataStoreHostApiSetup(id binaryMessenge binaryMessenger:binaryMessenger codec:FWFWKWebsiteDataStoreHostApiGetCodec()]; if (api) { - NSCAssert([api respondsToSelector:@selector - (removeDataFromDataStoreWithIdentifier: - ofTypes:secondsModifiedSinceEpoch:completion:)], - @"FWFWKWebsiteDataStoreHostApi api (%@) doesn't respond to " - @"@selector(removeDataFromDataStoreWithIdentifier:ofTypes:" - @"secondsModifiedSinceEpoch:completion:)", - api); + NSCAssert( + [api respondsToSelector:@selector + (removeDataFromDataStoreWithIdentifier:ofTypes:modifiedSince:completion:)], + @"FWFWKWebsiteDataStoreHostApi api (%@) doesn't respond to " + @"@selector(removeDataFromDataStoreWithIdentifier:ofTypes:modifiedSince:completion:)", + api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { NSArray *args = message; NSNumber *arg_instanceId = GetNullableObjectAtIndex(args, 0); - NSArray *arg_dataTypes = GetNullableObjectAtIndex(args, 1); - NSNumber *arg_secondsModifiedSinceEpoch = GetNullableObjectAtIndex(args, 2); + NSArray *arg_dataTypes = GetNullableObjectAtIndex(args, 1); + NSNumber *arg_modificationTimeInSecondsSinceEpoch = GetNullableObjectAtIndex(args, 2); [api removeDataFromDataStoreWithIdentifier:arg_instanceId ofTypes:arg_dataTypes - secondsModifiedSinceEpoch:arg_secondsModifiedSinceEpoch + modifiedSince:arg_modificationTimeInSecondsSinceEpoch completion:^(NSNumber *_Nullable output, FlutterError *_Nullable error) { callback(wrapResult(output, error)); @@ -404,28 +407,6 @@ - (FlutterStandardReader *)readerWithData:(NSData *)data { void FWFUIViewHostApiSetup(id binaryMessenger, NSObject *api) { - { - FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] - initWithName:@"dev.flutter.pigeon.UIViewHostApi.getContentOffset" - binaryMessenger:binaryMessenger - codec:FWFUIViewHostApiGetCodec()]; - if (api) { - NSCAssert([api respondsToSelector:@selector(contentOffsetForViewWithIdentifier:error:)], - @"FWFUIViewHostApi api (%@) doesn't respond to " - @"@selector(contentOffsetForViewWithIdentifier:error:)", - api); - [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; - NSNumber *arg_instanceId = GetNullableObjectAtIndex(args, 0); - FlutterError *error; - NSArray *output = [api contentOffsetForViewWithIdentifier:arg_instanceId - error:&error]; - callback(wrapResult(output, error)); - }]; - } else { - [channel setMessageHandler:nil]; - } - } { FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] initWithName:@"dev.flutter.pigeon.UIViewHostApi.setBackgroundColor" @@ -559,10 +540,9 @@ void FWFUIScrollViewHostApiSetup(id binaryMessenger, binaryMessenger:binaryMessenger codec:FWFUIScrollViewHostApiGetCodec()]; if (api) { - NSCAssert([api respondsToSelector:@selector(scrollByForScrollViewWithIdentifier: - toX:y:error:)], + NSCAssert([api respondsToSelector:@selector(scrollByForScrollViewWithIdentifier:x:y:error:)], @"FWFUIScrollViewHostApi api (%@) doesn't respond to " - @"@selector(scrollByForScrollViewWithIdentifier:toX:y:error:)", + @"@selector(scrollByForScrollViewWithIdentifier:x:y:error:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { NSArray *args = message; @@ -570,7 +550,7 @@ void FWFUIScrollViewHostApiSetup(id binaryMessenger, NSNumber *arg_x = GetNullableObjectAtIndex(args, 1); NSNumber *arg_y = GetNullableObjectAtIndex(args, 2); FlutterError *error; - [api scrollByForScrollViewWithIdentifier:arg_instanceId toX:arg_x y:arg_y error:&error]; + [api scrollByForScrollViewWithIdentifier:arg_instanceId x:arg_x y:arg_y error:&error]; callback(wrapResult(nil, error)); }]; } else { @@ -711,9 +691,9 @@ void FWFWKWebViewConfigurationHostApiSetup(id binaryMess if (api) { NSCAssert( [api respondsToSelector:@selector - (setAllowsInlineMediaPlaybackForConfigurationWithIdentifier:isAlowed:error:)], + (setAllowsInlineMediaPlaybackForConfigurationWithIdentifier:isAllowed:error:)], @"FWFWKWebViewConfigurationHostApi api (%@) doesn't respond to " - @"@selector(setAllowsInlineMediaPlaybackForConfigurationWithIdentifier:isAlowed:error:)", + @"@selector(setAllowsInlineMediaPlaybackForConfigurationWithIdentifier:isAllowed:error:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { NSArray *args = message; @@ -721,7 +701,7 @@ void FWFWKWebViewConfigurationHostApiSetup(id binaryMess NSNumber *arg_allow = GetNullableObjectAtIndex(args, 1); FlutterError *error; [api setAllowsInlineMediaPlaybackForConfigurationWithIdentifier:arg_instanceId - isAlowed:arg_allow + isAllowed:arg_allow error:&error]; callback(wrapResult(nil, error)); }]; @@ -1008,19 +988,20 @@ void FWFWKPreferencesHostApiSetup(id binaryMessenger, binaryMessenger:binaryMessenger codec:FWFWKPreferencesHostApiGetCodec()]; if (api) { - NSCAssert([api respondsToSelector:@selector(createFromWebViewConfiguration: - configurationIdentifier:error:)], - @"FWFWKPreferencesHostApi api (%@) doesn't respond to " - @"@selector(createFromWebViewConfiguration:configurationIdentifier:error:)", - api); + NSCAssert( + [api respondsToSelector:@selector(createFromWebViewConfigurationWithIdentifier: + configurationIdentifier:error:)], + @"FWFWKPreferencesHostApi api (%@) doesn't respond to " + @"@selector(createFromWebViewConfigurationWithIdentifier:configurationIdentifier:error:)", + api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { NSArray *args = message; NSNumber *arg_instanceId = GetNullableObjectAtIndex(args, 0); NSNumber *arg_configurationInstanceId = GetNullableObjectAtIndex(args, 1); FlutterError *error; - [api createFromWebViewConfiguration:arg_instanceId - configurationIdentifier:arg_configurationInstanceId - error:&error]; + [api createFromWebViewConfigurationWithIdentifier:arg_instanceId + configurationIdentifier:arg_configurationInstanceId + error:&error]; callback(wrapResult(nil, error)); }]; } else { @@ -1472,7 +1453,7 @@ - (nullable id)readValueOfType:(UInt8)type { return [FWFWKUserScriptInjectionTimeEnumData fromMap:[self readValue]]; case 135: - return [FWFWKWebsiteDataTypesEnumData fromMap:[self readValue]]; + return [FWFWKWebsiteDataTypeEnumData fromMap:[self readValue]]; default: return [super readValueOfType:type]; @@ -1505,7 +1486,7 @@ - (void)writeValue:(id)value { } else if ([value isKindOfClass:[FWFWKUserScriptInjectionTimeEnumData class]]) { [self writeByte:134]; [self writeValue:[value toMap]]; - } else if ([value isKindOfClass:[FWFWKWebsiteDataTypesEnumData class]]) { + } else if ([value isKindOfClass:[FWFWKWebsiteDataTypeEnumData class]]) { [self writeByte:135]; [self writeValue:[value toMap]]; } else { @@ -2107,17 +2088,20 @@ void FWFWKHttpCookieStoreHostApiSetup(id binaryMessenger binaryMessenger:binaryMessenger codec:FWFWKHttpCookieStoreHostApiGetCodec()]; if (api) { - NSCAssert([api respondsToSelector:@selector(setCookieForStoreWithIdentifier:cookie:error:)], + NSCAssert([api respondsToSelector:@selector(setCookieForStoreWithIdentifier: + cookie:completion:)], @"FWFWKHttpCookieStoreHostApi api (%@) doesn't respond to " - @"@selector(setCookieForStoreWithIdentifier:cookie:error:)", + @"@selector(setCookieForStoreWithIdentifier:cookie:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { NSArray *args = message; NSNumber *arg_instanceId = GetNullableObjectAtIndex(args, 0); FWFNSHttpCookieData *arg_cookie = GetNullableObjectAtIndex(args, 1); - FlutterError *error; - [api setCookieForStoreWithIdentifier:arg_instanceId cookie:arg_cookie error:&error]; - callback(wrapResult(nil, error)); + [api setCookieForStoreWithIdentifier:arg_instanceId + cookie:arg_cookie + completion:^(FlutterError *_Nullable error) { + callback(wrapResult(nil, error)); + }]; }]; } else { [channel setMessageHandler:nil]; diff --git a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFHTTPCookieStoreHostApi.h b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFHTTPCookieStoreHostApi.h new file mode 100644 index 000000000000..887c9f1b3d8b --- /dev/null +++ b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFHTTPCookieStoreHostApi.h @@ -0,0 +1,22 @@ +// 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 +#import + +#import "FWFGeneratedWebKitApis.h" +#import "FWFInstanceManager.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * Host api implementation for WKHTTPCookieStore. + * + * Handles creating WKHTTPCookieStore that intercommunicate with a paired Dart object. + */ +@interface FWFHTTPCookieStoreHostApiImpl : NSObject +- (instancetype)initWithInstanceManager:(FWFInstanceManager *)instanceManager; +@end + +NS_ASSUME_NONNULL_END diff --git a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFHTTPCookieStoreHostApi.m b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFHTTPCookieStoreHostApi.m new file mode 100644 index 000000000000..6ebd60a4ac40 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFHTTPCookieStoreHostApi.m @@ -0,0 +1,60 @@ +// 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 "FWFHTTPCookieStoreHostApi.h" +#import "FWFDataConverters.h" +#import "FWFWebsiteDataStoreHostApi.h" + +@interface FWFHTTPCookieStoreHostApiImpl () +@property(nonatomic) FWFInstanceManager *instanceManager; +@end + +@implementation FWFHTTPCookieStoreHostApiImpl +- (instancetype)initWithInstanceManager:(FWFInstanceManager *)instanceManager { + self = [self init]; + if (self) { + _instanceManager = instanceManager; + } + return self; +} + +- (WKHTTPCookieStore *)HTTPCookieStoreForIdentifier:(NSNumber *)instanceId + API_AVAILABLE(ios(11.0)) { + return (WKHTTPCookieStore *)[self.instanceManager instanceForIdentifier:instanceId.longValue]; +} + +- (void)createFromWebsiteDataStoreWithIdentifier:(nonnull NSNumber *)instanceId + dataStoreIdentifier:(nonnull NSNumber *)websiteDataStoreInstanceId + error:(FlutterError *_Nullable __autoreleasing *_Nonnull) + error { + if (@available(iOS 11.0, *)) { + WKWebsiteDataStore *dataStore = (WKWebsiteDataStore *)[self.instanceManager + instanceForIdentifier:websiteDataStoreInstanceId.longValue]; + [self.instanceManager addInstance:dataStore.httpCookieStore + withIdentifier:instanceId.longValue]; + } else { + *error = [FlutterError + errorWithCode:@"FWFUnsupportedVersionError" + message:@"WKWebsiteDataStore.httpCookieStore is only supported on versions 11+." + details:nil]; + } +} + +- (void)setCookieForStoreWithIdentifier:(nonnull NSNumber *)instanceId + cookie:(nonnull FWFNSHttpCookieData *)cookie + completion:(nonnull void (^)(FlutterError *_Nullable))completion { + NSHTTPCookie *nsCookie = FWFNSHTTPCookieFromCookieData(cookie); + + if (@available(iOS 11.0, *)) { + [[self HTTPCookieStoreForIdentifier:instanceId] setCookie:nsCookie + completionHandler:^{ + completion(nil); + }]; + } else { + completion([FlutterError errorWithCode:@"FWFUnsupportedVersionError" + message:@"setCookie is only supported on versions 11+." + details:nil]); + } +} +@end diff --git a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFNavigationDelegateHostApi.h b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFNavigationDelegateHostApi.h new file mode 100644 index 000000000000..fca1e83c86e0 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFNavigationDelegateHostApi.h @@ -0,0 +1,28 @@ +// 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 +#import + +#import "FWFGeneratedWebKitApis.h" +#import "FWFInstanceManager.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * Implementation of WKNavigationDelegate for FWFNavigationDelegateHostApiImpl. + */ +@interface FWFNavigationDelegate : NSObject +@end + +/** + * Host api implementation for WKNavigationDelegate. + * + * Handles creating WKNavigationDelegate that intercommunicate with a paired Dart object. + */ +@interface FWFNavigationDelegateHostApiImpl : NSObject +- (instancetype)initWithInstanceManager:(FWFInstanceManager *)instanceManager; +@end + +NS_ASSUME_NONNULL_END diff --git a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFNavigationDelegateHostApi.m b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFNavigationDelegateHostApi.m new file mode 100644 index 000000000000..188d83ff81b6 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFNavigationDelegateHostApi.m @@ -0,0 +1,40 @@ +// 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 "FWFNavigationDelegateHostApi.h" +#import "FWFWebViewConfigurationHostApi.h" + +@implementation FWFNavigationDelegate +@end + +@interface FWFNavigationDelegateHostApiImpl () +@property(nonatomic) FWFInstanceManager *instanceManager; +@end + +@implementation FWFNavigationDelegateHostApiImpl +- (instancetype)initWithInstanceManager:(FWFInstanceManager *)instanceManager { + self = [self init]; + if (self) { + _instanceManager = instanceManager; + } + return self; +} + +- (FWFNavigationDelegate *)navigationDelegateForIdentifier:(NSNumber *)instanceId { + return (FWFNavigationDelegate *)[self.instanceManager instanceForIdentifier:instanceId.longValue]; +} + +- (void)createWithIdentifier:(nonnull NSNumber *)instanceId + error:(FlutterError *_Nullable *_Nonnull)error { + FWFNavigationDelegate *navigationDelegate = [[FWFNavigationDelegate alloc] init]; + [self.instanceManager addInstance:navigationDelegate withIdentifier:instanceId.longValue]; +} + +- (void)setDidFinishNavigationForDelegateWithIdentifier:(nonnull NSNumber *)instanceId + functionIdentifier:(nullable NSNumber *)functionInstanceId + error:(FlutterError *_Nullable __autoreleasing + *_Nonnull)error { + // TODO(bparrishMines): Implement when callback method design is finalized. +} +@end diff --git a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFObjectHostApi.h b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFObjectHostApi.h new file mode 100644 index 000000000000..23c38fbe482d --- /dev/null +++ b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFObjectHostApi.h @@ -0,0 +1,21 @@ +// 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 + +#import "FWFGeneratedWebKitApis.h" +#import "FWFInstanceManager.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * Host api implementation for NSObject. + * + * Handles creating NSObject that intercommunicate with a paired Dart object. + */ +@interface FWFObjectHostApiImpl : NSObject +- (instancetype)initWithInstanceManager:(FWFInstanceManager *)instanceManager; +@end + +NS_ASSUME_NONNULL_END diff --git a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFObjectHostApi.m b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFObjectHostApi.m new file mode 100644 index 000000000000..b229c2e819a9 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFObjectHostApi.m @@ -0,0 +1,54 @@ +// 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 "FWFObjectHostApi.h" +#import "FWFDataConverters.h" + +@interface FWFObjectHostApiImpl () +@property(nonatomic) FWFInstanceManager *instanceManager; +@end + +@implementation FWFObjectHostApiImpl +- (instancetype)initWithInstanceManager:(FWFInstanceManager *)instanceManager { + self = [self init]; + if (self) { + _instanceManager = instanceManager; + } + return self; +} + +- (NSObject *)objectForIdentifier:(NSNumber *)instanceId { + return (NSObject *)[self.instanceManager instanceForIdentifier:instanceId.longValue]; +} + +- (void)addObserverForObjectWithIdentifier:(nonnull NSNumber *)instanceId + observerIdentifier:(nonnull NSNumber *)observer + keyPath:(nonnull NSString *)keyPath + options: + (nonnull NSArray *) + options + error:(FlutterError *_Nullable *_Nonnull)error { + NSKeyValueObservingOptions optionsInt = 0; + for (FWFNSKeyValueObservingOptionsEnumData *data in options) { + optionsInt |= FWFNSKeyValueObservingOptionsFromEnumData(data); + } + [[self objectForIdentifier:instanceId] addObserver:[self objectForIdentifier:observer] + forKeyPath:keyPath + options:optionsInt + context:nil]; +} + +- (void)removeObserverForObjectWithIdentifier:(nonnull NSNumber *)instanceId + observerIdentifier:(nonnull NSNumber *)observer + keyPath:(nonnull NSString *)keyPath + error:(FlutterError *_Nullable *_Nonnull)error { + [[self objectForIdentifier:instanceId] removeObserver:[self objectForIdentifier:observer] + forKeyPath:keyPath]; +} + +- (void)disposeObjectWithIdentifier:(nonnull NSNumber *)instanceId + error:(FlutterError *_Nullable *_Nonnull)error { + [self.instanceManager removeInstanceWithIdentifier:instanceId.longValue]; +} +@end diff --git a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFPreferencesHostApi.h b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFPreferencesHostApi.h new file mode 100644 index 000000000000..de2d26491a58 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFPreferencesHostApi.h @@ -0,0 +1,22 @@ +// 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 +#import + +#import "FWFGeneratedWebKitApis.h" +#import "FWFInstanceManager.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * Host api implementation for WKPreferences. + * + * Handles creating WKPreferences that intercommunicate with a paired Dart object. + */ +@interface FWFPreferencesHostApiImpl : NSObject +- (instancetype)initWithInstanceManager:(FWFInstanceManager *)instanceManager; +@end + +NS_ASSUME_NONNULL_END diff --git a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFPreferencesHostApi.m b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFPreferencesHostApi.m new file mode 100644 index 000000000000..f907d211f08e --- /dev/null +++ b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFPreferencesHostApi.m @@ -0,0 +1,44 @@ +// 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 "FWFPreferencesHostApi.h" +#import "FWFWebViewConfigurationHostApi.h" + +@interface FWFPreferencesHostApiImpl () +@property(nonatomic) FWFInstanceManager *instanceManager; +@end + +@implementation FWFPreferencesHostApiImpl +- (instancetype)initWithInstanceManager:(FWFInstanceManager *)instanceManager { + self = [self init]; + if (self) { + _instanceManager = instanceManager; + } + return self; +} + +- (WKPreferences *)preferencesForIdentifier:(NSNumber *)instanceId { + return (WKPreferences *)[self.instanceManager instanceForIdentifier:instanceId.longValue]; +} + +- (void)createWithIdentifier:(nonnull NSNumber *)instanceId + error:(FlutterError *_Nullable *_Nonnull)error { + WKPreferences *preferences = [[WKPreferences alloc] init]; + [self.instanceManager addInstance:preferences withIdentifier:instanceId.longValue]; +} + +- (void)createFromWebViewConfigurationWithIdentifier:(nonnull NSNumber *)instanceId + configurationIdentifier:(nonnull NSNumber *)configurationInstanceId + error:(FlutterError *_Nullable *_Nonnull)error { + WKWebViewConfiguration *configuration = (WKWebViewConfiguration *)[self.instanceManager + instanceForIdentifier:configurationInstanceId.longValue]; + [self.instanceManager addInstance:configuration.preferences withIdentifier:instanceId.longValue]; +} + +- (void)setJavaScriptEnabledForPreferencesWithIdentifier:(nonnull NSNumber *)instanceId + isEnabled:(nonnull NSNumber *)enabled + error:(FlutterError *_Nullable *_Nonnull)error { + [[self preferencesForIdentifier:instanceId] setJavaScriptEnabled:enabled.boolValue]; +} +@end diff --git a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFScriptMessageHandlerHostApi.h b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFScriptMessageHandlerHostApi.h new file mode 100644 index 000000000000..7440862ce4e4 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFScriptMessageHandlerHostApi.h @@ -0,0 +1,28 @@ +// 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 +#import + +#import "FWFGeneratedWebKitApis.h" +#import "FWFInstanceManager.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * Implementation of WKScriptMessageHandler for FWFScriptMessageHandlerHostApiImpl. + */ +@interface FWFScriptMessageHandler : NSObject +@end + +/** + * Host api implementation for WKScriptMessageHandler. + * + * Handles creating WKScriptMessageHandler that intercommunicate with a paired Dart object. + */ +@interface FWFScriptMessageHandlerHostApiImpl : NSObject +- (instancetype)initWithInstanceManager:(FWFInstanceManager *)instanceManager; +@end + +NS_ASSUME_NONNULL_END diff --git a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFScriptMessageHandlerHostApi.m b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFScriptMessageHandlerHostApi.m new file mode 100644 index 000000000000..37662b5fc9f4 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFScriptMessageHandlerHostApi.m @@ -0,0 +1,37 @@ +// 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 "FWFScriptMessageHandlerHostApi.h" +#import "FWFDataConverters.h" + +@implementation FWFScriptMessageHandler +- (void)userContentController:(nonnull WKUserContentController *)userContentController + didReceiveScriptMessage:(nonnull WKScriptMessage *)message { +} +@end + +@interface FWFScriptMessageHandlerHostApiImpl () +@property(nonatomic) FWFInstanceManager *instanceManager; +@end + +@implementation FWFScriptMessageHandlerHostApiImpl +- (instancetype)initWithInstanceManager:(FWFInstanceManager *)instanceManager { + self = [self init]; + if (self) { + _instanceManager = instanceManager; + } + return self; +} + +- (FWFScriptMessageHandler *)scriptMessageHandlerForIdentifier:(NSNumber *)instanceId { + return (FWFScriptMessageHandler *)[self.instanceManager + instanceForIdentifier:instanceId.longValue]; +} + +- (void)createWithIdentifier:(nonnull NSNumber *)instanceId + error:(FlutterError *_Nullable *_Nonnull)error { + FWFScriptMessageHandler *scriptMessageHandler = [[FWFScriptMessageHandler alloc] init]; + [self.instanceManager addInstance:scriptMessageHandler withIdentifier:instanceId.longValue]; +} +@end diff --git a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFScrollViewHostApi.h b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFScrollViewHostApi.h new file mode 100644 index 000000000000..25f373f374e3 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFScrollViewHostApi.h @@ -0,0 +1,22 @@ +// 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 +#import + +#import "FWFGeneratedWebKitApis.h" +#import "FWFInstanceManager.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * Host api implementation for UIScrollView. + * + * Handles creating UIScrollView that intercommunicate with a paired Dart object. + */ +@interface FWFScrollViewHostApiImpl : NSObject +- (instancetype)initWithInstanceManager:(FWFInstanceManager *)instanceManager; +@end + +NS_ASSUME_NONNULL_END diff --git a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFScrollViewHostApi.m b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFScrollViewHostApi.m new file mode 100644 index 000000000000..a7522995e0e1 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFScrollViewHostApi.m @@ -0,0 +1,57 @@ +// 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 "FWFScrollViewHostApi.h" +#import "FWFWebViewHostApi.h" + +@interface FWFScrollViewHostApiImpl () +@property(nonatomic) FWFInstanceManager *instanceManager; +@end + +@implementation FWFScrollViewHostApiImpl +- (instancetype)initWithInstanceManager:(FWFInstanceManager *)instanceManager { + self = [self init]; + if (self) { + _instanceManager = instanceManager; + } + return self; +} + +- (UIScrollView *)scrollViewForIdentifier:(NSNumber *)instanceId { + return (UIScrollView *)[self.instanceManager instanceForIdentifier:instanceId.longValue]; +} + +- (void)createFromWebViewWithIdentifier:(nonnull NSNumber *)instanceId + webViewIdentifier:(nonnull NSNumber *)webViewInstanceId + error:(FlutterError *_Nullable __autoreleasing *_Nonnull)error { + WKWebView *webView = + (WKWebView *)[self.instanceManager instanceForIdentifier:webViewInstanceId.longValue]; + [self.instanceManager addInstance:webView.scrollView withIdentifier:instanceId.longValue]; +} + +- (NSArray *) + contentOffsetForScrollViewWithIdentifier:(nonnull NSNumber *)instanceId + error:(FlutterError *_Nullable *_Nonnull)error { + CGPoint point = [[self scrollViewForIdentifier:instanceId] contentOffset]; + return @[ @(point.x), @(point.y) ]; +} + +- (void)scrollByForScrollViewWithIdentifier:(nonnull NSNumber *)instanceId + x:(nonnull NSNumber *)x + y:(nonnull NSNumber *)y + error:(FlutterError *_Nullable *_Nonnull)error { + UIScrollView *scrollView = [self scrollViewForIdentifier:instanceId]; + CGPoint contentOffset = scrollView.contentOffset; + [scrollView setContentOffset:CGPointMake(contentOffset.x + x.doubleValue, + contentOffset.y + y.doubleValue)]; +} + +- (void)setContentOffsetForScrollViewWithIdentifier:(nonnull NSNumber *)instanceId + toX:(nonnull NSNumber *)x + y:(nonnull NSNumber *)y + error:(FlutterError *_Nullable *_Nonnull)error { + [[self scrollViewForIdentifier:instanceId] + setContentOffset:CGPointMake(x.doubleValue, y.doubleValue)]; +} +@end diff --git a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFUIDelegateHostApi.h b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFUIDelegateHostApi.h new file mode 100644 index 000000000000..8795b00e9001 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFUIDelegateHostApi.h @@ -0,0 +1,28 @@ +// 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 +#import + +#import "FWFGeneratedWebKitApis.h" +#import "FWFInstanceManager.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * Implementation of WKUIDelegate for FWFUIDelegateHostApiImpl. + */ +@interface FWFUIDelegate : NSObject +@end + +/** + * Host api implementation for WKUIDelegate. + * + * Handles creating WKUIDelegate that intercommunicate with a paired Dart object. + */ +@interface FWFUIDelegateHostApiImpl : NSObject +- (instancetype)initWithInstanceManager:(FWFInstanceManager *)instanceManager; +@end + +NS_ASSUME_NONNULL_END diff --git a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFUIDelegateHostApi.m b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFUIDelegateHostApi.m new file mode 100644 index 000000000000..2621c5dde287 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFUIDelegateHostApi.m @@ -0,0 +1,33 @@ +// 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 "FWFUIDelegateHostApi.h" +#import "FWFWebViewConfigurationHostApi.h" + +@implementation FWFUIDelegate +@end + +@interface FWFUIDelegateHostApiImpl () +@property(nonatomic) FWFInstanceManager *instanceManager; +@end + +@implementation FWFUIDelegateHostApiImpl +- (instancetype)initWithInstanceManager:(FWFInstanceManager *)instanceManager { + self = [self init]; + if (self) { + _instanceManager = instanceManager; + } + return self; +} + +- (FWFUIDelegate *)delegateForIdentifier:(NSNumber *)instanceId { + return (FWFUIDelegate *)[self.instanceManager instanceForIdentifier:instanceId.longValue]; +} + +- (void)createWithIdentifier:(nonnull NSNumber *)instanceId + error:(FlutterError *_Nullable *_Nonnull)error { + FWFUIDelegate *uIDelegate = [[FWFUIDelegate alloc] init]; + [self.instanceManager addInstance:uIDelegate withIdentifier:instanceId.longValue]; +} +@end diff --git a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFUIViewHostApi.h b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFUIViewHostApi.h new file mode 100644 index 000000000000..82edd6b742ca --- /dev/null +++ b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFUIViewHostApi.h @@ -0,0 +1,21 @@ +// 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 + +#import "FWFGeneratedWebKitApis.h" +#import "FWFInstanceManager.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * Host api implementation for UIView. + * + * Handles creating UIView that intercommunicate with a paired Dart object. + */ +@interface FWFUIViewHostApiImpl : NSObject +- (instancetype)initWithInstanceManager:(FWFInstanceManager *)instanceManager; +@end + +NS_ASSUME_NONNULL_END diff --git a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFUIViewHostApi.m b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFUIViewHostApi.m new file mode 100644 index 000000000000..b2c1f639d1f6 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFUIViewHostApi.m @@ -0,0 +1,43 @@ +// 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 "FWFUIViewHostApi.h" + +@interface FWFUIViewHostApiImpl () +@property(nonatomic) FWFInstanceManager *instanceManager; +@end + +@implementation FWFUIViewHostApiImpl +- (instancetype)initWithInstanceManager:(FWFInstanceManager *)instanceManager { + self = [self init]; + if (self) { + _instanceManager = instanceManager; + } + return self; +} + +- (UIView *)viewForIdentifier:(NSNumber *)instanceId { + return (UIView *)[self.instanceManager instanceForIdentifier:instanceId.longValue]; +} + +- (void)setBackgroundColorForViewWithIdentifier:(nonnull NSNumber *)instanceId + toValue:(nullable NSNumber *)color + error:(FlutterError *_Nullable *_Nonnull)error { + if (!color) { + [[self viewForIdentifier:instanceId] setBackgroundColor:nil]; + } + int colorInt = color.intValue; + UIColor *colorObject = [UIColor colorWithRed:(colorInt >> 16 & 0xff) / 255.0 + green:(colorInt >> 8 & 0xff) / 255.0 + blue:(colorInt & 0xff) / 255.0 + alpha:(colorInt >> 24 & 0xff) / 255.0]; + [[self viewForIdentifier:instanceId] setBackgroundColor:colorObject]; +} + +- (void)setOpaqueForViewWithIdentifier:(nonnull NSNumber *)instanceId + isOpaque:(nonnull NSNumber *)opaque + error:(FlutterError *_Nullable *_Nonnull)error { + [[self viewForIdentifier:instanceId] setOpaque:opaque.boolValue]; +} +@end diff --git a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFUserContentControllerHostApi.h b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFUserContentControllerHostApi.h new file mode 100644 index 000000000000..f0e5a1383ac3 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFUserContentControllerHostApi.h @@ -0,0 +1,22 @@ +// 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 +#import + +#import "FWFGeneratedWebKitApis.h" +#import "FWFInstanceManager.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * Host api implementation for WKUserContentController. + * + * Handles creating WKUserContentController that intercommunicate with a paired Dart object. + */ +@interface FWFUserContentControllerHostApiImpl : NSObject +- (instancetype)initWithInstanceManager:(FWFInstanceManager *)instanceManager; +@end + +NS_ASSUME_NONNULL_END diff --git a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFUserContentControllerHostApi.m b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFUserContentControllerHostApi.m new file mode 100644 index 000000000000..2db7cff0b68e --- /dev/null +++ b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFUserContentControllerHostApi.m @@ -0,0 +1,80 @@ +// 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 "FWFUserContentControllerHostApi.h" +#import "FWFDataConverters.h" +#import "FWFWebViewConfigurationHostApi.h" + +@interface FWFUserContentControllerHostApiImpl () +@property(nonatomic) FWFInstanceManager *instanceManager; +@end + +@implementation FWFUserContentControllerHostApiImpl +- (instancetype)initWithInstanceManager:(FWFInstanceManager *)instanceManager { + self = [self init]; + if (self) { + _instanceManager = instanceManager; + } + return self; +} + +- (WKUserContentController *)userContentControllerForIdentifier:(NSNumber *)instanceId { + return (WKUserContentController *)[self.instanceManager + instanceForIdentifier:instanceId.longValue]; +} + +- (void)createFromWebViewConfigurationWithIdentifier:(nonnull NSNumber *)instanceId + configurationIdentifier:(nonnull NSNumber *)configurationInstanceId + error:(FlutterError *_Nullable *_Nonnull)error { + WKWebViewConfiguration *configuration = (WKWebViewConfiguration *)[self.instanceManager + instanceForIdentifier:configurationInstanceId.longValue]; + [self.instanceManager addInstance:configuration.userContentController + withIdentifier:instanceId.longValue]; +} + +- (void)addScriptMessageHandlerForControllerWithIdentifier:(nonnull NSNumber *)instanceId + handlerIdentifier:(nonnull NSNumber *)handler + ofName:(nonnull NSString *)name + error: + (FlutterError *_Nullable *_Nonnull)error { + [[self userContentControllerForIdentifier:instanceId] + addScriptMessageHandler:(id)[self.instanceManager + instanceForIdentifier:handler.longValue] + name:name]; +} + +- (void)removeScriptMessageHandlerForControllerWithIdentifier:(nonnull NSNumber *)instanceId + name:(nonnull NSString *)name + error:(FlutterError *_Nullable *_Nonnull) + error { + [[self userContentControllerForIdentifier:instanceId] removeScriptMessageHandlerForName:name]; +} + +- (void)removeAllScriptMessageHandlersForControllerWithIdentifier:(nonnull NSNumber *)instanceId + error: + (FlutterError *_Nullable *_Nonnull) + error { + if (@available(iOS 14.0, *)) { + [[self userContentControllerForIdentifier:instanceId] removeAllScriptMessageHandlers]; + } else { + *error = [FlutterError + errorWithCode:@"FWFUnsupportedVersionError" + message:@"removeAllScriptMessageHandlers is only supported on versions 14+." + details:nil]; + } +} + +- (void)addUserScriptForControllerWithIdentifier:(nonnull NSNumber *)instanceId + userScript:(nonnull FWFWKUserScriptData *)userScript + error:(FlutterError *_Nullable *_Nonnull)error { + [[self userContentControllerForIdentifier:instanceId] + addUserScript:FWFWKUserScriptFromScriptData(userScript)]; +} + +- (void)removeAllUserScriptsForControllerWithIdentifier:(nonnull NSNumber *)instanceId + error:(FlutterError *_Nullable *_Nonnull)error { + [[self userContentControllerForIdentifier:instanceId] removeAllUserScripts]; +} + +@end diff --git a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFWebViewConfigurationHostApi.h b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFWebViewConfigurationHostApi.h new file mode 100644 index 000000000000..4c01d9354107 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFWebViewConfigurationHostApi.h @@ -0,0 +1,22 @@ +// 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 +#import + +#import "FWFGeneratedWebKitApis.h" +#import "FWFInstanceManager.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * Host api implementation for WKWebViewConfiguration. + * + * Handles creating WKWebViewConfiguration that intercommunicate with a paired Dart object. + */ +@interface FWFWebViewConfigurationHostApiImpl : NSObject +- (instancetype)initWithInstanceManager:(FWFInstanceManager *)instanceManager; +@end + +NS_ASSUME_NONNULL_END diff --git a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFWebViewConfigurationHostApi.m b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFWebViewConfigurationHostApi.m new file mode 100644 index 000000000000..0b239daebf99 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFWebViewConfigurationHostApi.m @@ -0,0 +1,87 @@ +// 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 "FWFWebViewConfigurationHostApi.h" +#import "FWFDataConverters.h" +#import "FWFWebViewConfigurationHostApi.h" + +@interface FWFWebViewConfigurationHostApiImpl () +@property(nonatomic) FWFInstanceManager *instanceManager; +@end + +@implementation FWFWebViewConfigurationHostApiImpl +- (instancetype)initWithInstanceManager:(FWFInstanceManager *)instanceManager { + self = [self init]; + if (self) { + _instanceManager = instanceManager; + } + return self; +} + +- (WKWebViewConfiguration *)webViewConfigurationForIdentifier:(NSNumber *)instanceId { + return (WKWebViewConfiguration *)[self.instanceManager + instanceForIdentifier:instanceId.longValue]; +} + +- (void)createWithIdentifier:(nonnull NSNumber *)instanceId + error:(FlutterError *_Nullable *_Nonnull)error { + WKWebViewConfiguration *webViewConfiguration = [[WKWebViewConfiguration alloc] init]; + [self.instanceManager addInstance:webViewConfiguration withIdentifier:instanceId.longValue]; +} + +- (void)createFromWebViewWithIdentifier:(nonnull NSNumber *)instanceId + webViewIdentifier:(nonnull NSNumber *)webViewInstanceId + error:(FlutterError *_Nullable __autoreleasing *_Nonnull)error { + WKWebView *webView = + (WKWebView *)[self.instanceManager instanceForIdentifier:webViewInstanceId.longValue]; + [self.instanceManager addInstance:webView.configuration withIdentifier:instanceId.longValue]; +} + +- (void)setAllowsInlineMediaPlaybackForConfigurationWithIdentifier:(nonnull NSNumber *)instanceId + isAllowed:(nonnull NSNumber *)allow + error: + (FlutterError *_Nullable *_Nonnull) + error { + [[self webViewConfigurationForIdentifier:instanceId] + setAllowsInlineMediaPlayback:allow.boolValue]; +} + +- (void) + setMediaTypesRequiresUserActionForConfigurationWithIdentifier:(nonnull NSNumber *)instanceId + forTypes: + (nonnull NSArray< + FWFWKAudiovisualMediaTypeEnumData + *> *)types + error: + (FlutterError *_Nullable *_Nonnull) + error { + NSAssert(types.count, @"Types must not be empty."); + + WKWebViewConfiguration *configuration = + (WKWebViewConfiguration *)[self webViewConfigurationForIdentifier:instanceId]; + if (@available(iOS 10.0, *)) { + WKAudiovisualMediaTypes typesInt = 0; + for (FWFWKAudiovisualMediaTypeEnumData *data in types) { + typesInt |= FWFWKAudiovisualMediaTypeFromEnumData(data); + } + [configuration setMediaTypesRequiringUserActionForPlayback:typesInt]; + } else { + for (FWFWKAudiovisualMediaTypeEnumData *data in types) { + switch (data.value) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + case FWFWKAudiovisualMediaTypeEnumNone: + configuration.requiresUserActionForMediaPlayback = false; + break; + case FWFWKAudiovisualMediaTypeEnumAudio: + case FWFWKAudiovisualMediaTypeEnumVideo: + case FWFWKAudiovisualMediaTypeEnumAll: + configuration.requiresUserActionForMediaPlayback = true; + break; +#pragma clang diagnostic pop + } + } + } +} +@end diff --git a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFWebsiteDataStoreHostApi.h b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFWebsiteDataStoreHostApi.h new file mode 100644 index 000000000000..72f00e032ee4 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFWebsiteDataStoreHostApi.h @@ -0,0 +1,22 @@ +// 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 +#import + +#import "FWFGeneratedWebKitApis.h" +#import "FWFInstanceManager.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * Host api implementation for WKWebsiteDataStore. + * + * Handles creating WKWebsiteDataStore that intercommunicate with a paired Dart object. + */ +@interface FWFWebsiteDataStoreHostApiImpl : NSObject +- (instancetype)initWithInstanceManager:(FWFInstanceManager *)instanceManager; +@end + +NS_ASSUME_NONNULL_END diff --git a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFWebsiteDataStoreHostApi.m b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFWebsiteDataStoreHostApi.m new file mode 100644 index 000000000000..e052ae03543c --- /dev/null +++ b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFWebsiteDataStoreHostApi.m @@ -0,0 +1,67 @@ +// 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 "FWFWebsiteDataStoreHostApi.h" +#import "FWFDataConverters.h" +#import "FWFWebViewConfigurationHostApi.h" + +@interface FWFWebsiteDataStoreHostApiImpl () +@property(nonatomic) FWFInstanceManager *instanceManager; +@end + +@implementation FWFWebsiteDataStoreHostApiImpl +- (instancetype)initWithInstanceManager:(FWFInstanceManager *)instanceManager { + self = [self init]; + if (self) { + _instanceManager = instanceManager; + } + return self; +} + +- (WKWebsiteDataStore *)websiteDataStoreForIdentifier:(NSNumber *)instanceId { + return (WKWebsiteDataStore *)[self.instanceManager instanceForIdentifier:instanceId.longValue]; +} + +- (void)createFromWebViewConfigurationWithIdentifier:(nonnull NSNumber *)instanceId + configurationIdentifier:(nonnull NSNumber *)configurationInstanceId + error:(FlutterError *_Nullable *_Nonnull)error { + WKWebViewConfiguration *configuration = (WKWebViewConfiguration *)[self.instanceManager + instanceForIdentifier:configurationInstanceId.longValue]; + [self.instanceManager addInstance:configuration.websiteDataStore + withIdentifier:instanceId.longValue]; +} + +- (void)createDefaultDataStoreWithIdentifier:(nonnull NSNumber *)instanceId + error:(FlutterError *_Nullable __autoreleasing *_Nonnull) + error { + [self.instanceManager addInstance:[WKWebsiteDataStore defaultDataStore] + withIdentifier:instanceId.longValue]; +} + +- (void) + removeDataFromDataStoreWithIdentifier:(nonnull NSNumber *)instanceId + ofTypes: + (nonnull NSArray *)dataTypes + modifiedSince:(nonnull NSNumber *)modificationTimeInSecondsSinceEpoch + completion:(nonnull void (^)(NSNumber *_Nullable, + FlutterError *_Nullable))completion { + NSMutableSet *stringDataTypes = [NSMutableSet set]; + for (FWFWKWebsiteDataTypeEnumData *type in dataTypes) { + [stringDataTypes addObject:FWFWKWebsiteDataTypeFromEnumData(type)]; + } + + WKWebsiteDataStore *dataStore = [self websiteDataStoreForIdentifier:instanceId]; + [dataStore + fetchDataRecordsOfTypes:stringDataTypes + completionHandler:^(NSArray *records) { + [dataStore + removeDataOfTypes:stringDataTypes + modifiedSince:[NSDate dateWithTimeIntervalSince1970: + modificationTimeInSecondsSinceEpoch.doubleValue] + completionHandler:^{ + completion(@(records.count > 0), nil); + }]; + }]; +} +@end diff --git a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/webview-umbrella.h b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/webview-umbrella.h index 9a7fd1b5ef3f..0aa409e4b31f 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/webview-umbrella.h +++ b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/webview-umbrella.h @@ -9,7 +9,18 @@ #import #import #import +#import #import +#import +#import +#import +#import +#import +#import +#import +#import +#import #import +#import #import #import diff --git a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/common/web_kit.pigeon.dart b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/common/web_kit.pigeon.dart index fa52b43c396e..f84ba68bfbc1 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/common/web_kit.pigeon.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/common/web_kit.pigeon.dart @@ -45,14 +45,14 @@ enum WKAudiovisualMediaTypeEnum { all, } -enum WKWebsiteDataTypesEnum { +enum WKWebsiteDataTypeEnum { cookies, memoryCache, diskCache, offlineWebApplicationCache, - localStroage, + localStorage, sessionStorage, - sqlDatabases, + webSQLDatabases, indexedDBDatabases, } @@ -80,115 +80,105 @@ enum NSHttpCookiePropertyKeyEnum { class NSKeyValueObservingOptionsEnumData { NSKeyValueObservingOptionsEnumData({ - this.value, + required this.value, }); - NSKeyValueObservingOptionsEnum? value; + NSKeyValueObservingOptionsEnum value; Object encode() { final Map pigeonMap = {}; - pigeonMap['value'] = value?.index; + pigeonMap['value'] = value.index; return pigeonMap; } static NSKeyValueObservingOptionsEnumData decode(Object message) { final Map pigeonMap = message as Map; return NSKeyValueObservingOptionsEnumData( - value: pigeonMap['value'] != null - ? NSKeyValueObservingOptionsEnum.values[pigeonMap['value']! as int] - : null, + value: NSKeyValueObservingOptionsEnum.values[pigeonMap['value']! as int], ); } } class WKUserScriptInjectionTimeEnumData { WKUserScriptInjectionTimeEnumData({ - this.value, + required this.value, }); - WKUserScriptInjectionTimeEnum? value; + WKUserScriptInjectionTimeEnum value; Object encode() { final Map pigeonMap = {}; - pigeonMap['value'] = value?.index; + pigeonMap['value'] = value.index; return pigeonMap; } static WKUserScriptInjectionTimeEnumData decode(Object message) { final Map pigeonMap = message as Map; return WKUserScriptInjectionTimeEnumData( - value: pigeonMap['value'] != null - ? WKUserScriptInjectionTimeEnum.values[pigeonMap['value']! as int] - : null, + value: WKUserScriptInjectionTimeEnum.values[pigeonMap['value']! as int], ); } } class WKAudiovisualMediaTypeEnumData { WKAudiovisualMediaTypeEnumData({ - this.value, + required this.value, }); - WKAudiovisualMediaTypeEnum? value; + WKAudiovisualMediaTypeEnum value; Object encode() { final Map pigeonMap = {}; - pigeonMap['value'] = value?.index; + pigeonMap['value'] = value.index; return pigeonMap; } static WKAudiovisualMediaTypeEnumData decode(Object message) { final Map pigeonMap = message as Map; return WKAudiovisualMediaTypeEnumData( - value: pigeonMap['value'] != null - ? WKAudiovisualMediaTypeEnum.values[pigeonMap['value']! as int] - : null, + value: WKAudiovisualMediaTypeEnum.values[pigeonMap['value']! as int], ); } } -class WKWebsiteDataTypesEnumData { - WKWebsiteDataTypesEnumData({ - this.value, +class WKWebsiteDataTypeEnumData { + WKWebsiteDataTypeEnumData({ + required this.value, }); - WKWebsiteDataTypesEnum? value; + WKWebsiteDataTypeEnum value; Object encode() { final Map pigeonMap = {}; - pigeonMap['value'] = value?.index; + pigeonMap['value'] = value.index; return pigeonMap; } - static WKWebsiteDataTypesEnumData decode(Object message) { + static WKWebsiteDataTypeEnumData decode(Object message) { final Map pigeonMap = message as Map; - return WKWebsiteDataTypesEnumData( - value: pigeonMap['value'] != null - ? WKWebsiteDataTypesEnum.values[pigeonMap['value']! as int] - : null, + return WKWebsiteDataTypeEnumData( + value: WKWebsiteDataTypeEnum.values[pigeonMap['value']! as int], ); } } class NSHttpCookiePropertyKeyEnumData { NSHttpCookiePropertyKeyEnumData({ - this.value, + required this.value, }); - NSHttpCookiePropertyKeyEnum? value; + NSHttpCookiePropertyKeyEnum value; Object encode() { final Map pigeonMap = {}; - pigeonMap['value'] = value?.index; + pigeonMap['value'] = value.index; return pigeonMap; } static NSHttpCookiePropertyKeyEnumData decode(Object message) { final Map pigeonMap = message as Map; return NSHttpCookiePropertyKeyEnumData( - value: pigeonMap['value'] != null - ? NSHttpCookiePropertyKeyEnum.values[pigeonMap['value']! as int] - : null, + value: NSHttpCookiePropertyKeyEnum.values[pigeonMap['value']! as int], ); } } @@ -262,22 +252,27 @@ class WKUserScriptData { class NSHttpCookieData { NSHttpCookieData({ - required this.properties, + required this.propertyKeys, + required this.propertyValues, }); - Map properties; + List propertyKeys; + List propertyValues; Object encode() { final Map pigeonMap = {}; - pigeonMap['properties'] = properties; + pigeonMap['propertyKeys'] = propertyKeys; + pigeonMap['propertyValues'] = propertyValues; return pigeonMap; } static NSHttpCookieData decode(Object message) { final Map pigeonMap = message as Map; return NSHttpCookieData( - properties: (pigeonMap['properties'] as Map?)! - .cast(), + propertyKeys: (pigeonMap['propertyKeys'] as List?)! + .cast(), + propertyValues: + (pigeonMap['propertyValues'] as List?)!.cast(), ); } } @@ -286,7 +281,7 @@ class _WKWebsiteDataStoreHostApiCodec extends StandardMessageCodec { const _WKWebsiteDataStoreHostApiCodec(); @override void writeValue(WriteBuffer buffer, Object? value) { - if (value is WKWebsiteDataTypesEnumData) { + if (value is WKWebsiteDataTypeEnumData) { buffer.putUint8(128); writeValue(buffer, value.encode()); } else { @@ -298,7 +293,7 @@ class _WKWebsiteDataStoreHostApiCodec extends StandardMessageCodec { Object? readValueOfType(int type, ReadBuffer buffer) { switch (type) { case 128: - return WKWebsiteDataTypesEnumData.decode(readValue(buffer)!); + return WKWebsiteDataTypeEnumData.decode(readValue(buffer)!); default: return super.readValueOfType(type, buffer); @@ -371,15 +366,15 @@ class WKWebsiteDataStoreHostApi { Future removeDataOfTypes( int arg_instanceId, - List arg_dataTypes, - double arg_secondsModifiedSinceEpoch) async { + List arg_dataTypes, + double arg_modificationTimeInSecondsSinceEpoch) async { final BasicMessageChannel channel = BasicMessageChannel( 'dev.flutter.pigeon.WKWebsiteDataStoreHostApi.removeDataOfTypes', codec, binaryMessenger: _binaryMessenger); final Map? replyMap = await channel.send([ arg_instanceId, arg_dataTypes, - arg_secondsModifiedSinceEpoch + arg_modificationTimeInSecondsSinceEpoch ]) as Map?; if (replyMap == null) { throw PlatformException( @@ -420,35 +415,6 @@ class UIViewHostApi { static const MessageCodec codec = _UIViewHostApiCodec(); - Future> getContentOffset(int arg_instanceId) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.UIViewHostApi.getContentOffset', codec, - binaryMessenger: _binaryMessenger); - final Map? replyMap = - await channel.send([arg_instanceId]) as Map?; - if (replyMap == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyMap['error'] != null) { - final Map error = - (replyMap['error'] as Map?)!; - throw PlatformException( - code: (error['code'] as String?)!, - message: error['message'] as String?, - details: error['details'], - ); - } else if (replyMap['result'] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (replyMap['result'] as List?)!.cast(); - } - } - Future setBackgroundColor(int arg_instanceId, int? arg_value) async { final BasicMessageChannel channel = BasicMessageChannel( 'dev.flutter.pigeon.UIViewHostApi.setBackgroundColor', codec, @@ -1352,7 +1318,7 @@ class _WKWebViewHostApiCodec extends StandardMessageCodec { } else if (value is WKUserScriptInjectionTimeEnumData) { buffer.putUint8(134); writeValue(buffer, value.encode()); - } else if (value is WKWebsiteDataTypesEnumData) { + } else if (value is WKWebsiteDataTypeEnumData) { buffer.putUint8(135); writeValue(buffer, value.encode()); } else { @@ -1385,7 +1351,7 @@ class _WKWebViewHostApiCodec extends StandardMessageCodec { return WKUserScriptInjectionTimeEnumData.decode(readValue(buffer)!); case 135: - return WKWebsiteDataTypesEnumData.decode(readValue(buffer)!); + return WKWebsiteDataTypeEnumData.decode(readValue(buffer)!); default: return super.readValueOfType(type, buffer); 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 ec7bb5377de0..5c127c5654c6 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 @@ -146,6 +146,9 @@ enum NSHttpCookiePropertyKey { /// A String indicating the same-site policy for the cookie. /// + /// This is only supported on iOS version 13+. This value will be ignored on + /// versions < 13. + /// /// See https://developer.apple.com/documentation/foundation/nshttpcookiesamesitepolicy. sameSitePolicy, diff --git a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/web_kit/web_kit.dart b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/web_kit/web_kit.dart index ab63db67bba1..88f763fe6ba3 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/web_kit/web_kit.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/web_kit/web_kit.dart @@ -53,7 +53,7 @@ enum WKAudiovisualMediaType { /// Types of data that websites store. /// /// See https://developer.apple.com/documentation/webkit/wkwebsitedatarecord/data_store_record_types?language=objc. -enum WKWebsiteDataTypes { +enum WKWebsiteDataType { /// Cookies. cookies, @@ -67,13 +67,13 @@ enum WKWebsiteDataTypes { offlineWebApplicationCache, /// HTML local storage. - localStroage, + localStorage, /// HTML session storage. sessionStorage, /// WebSQL databases. - sqlDatabases, + webSQLDatabases, /// IndexedDB databases. indexedDBDatabases, @@ -291,7 +291,7 @@ class WKWebsiteDataStore { /// /// Returns whether any data was removed. Future removeDataOfTypes( - Set dataTypes, + Set dataTypes, DateTime since, ) { return _websiteDataStoreApi.removeDataOfTypesForInstances( @@ -440,7 +440,10 @@ class WKUserContentController { ); } - /// Uninstalls all custom message handlers associated with the user content controller. + /// Uninstalls all custom message handlers associated with the user content + /// controller. + /// + /// Only supported on iOS version 14+. Future removeAllScriptMessageHandlers() { return _userContentControllerApi.removeAllScriptMessageHandlersForInstances( this, @@ -550,6 +553,7 @@ class WKWebViewConfiguration { Future setMediaTypesRequiringUserActionForPlayback( Set types, ) { + assert(types.isNotEmpty); return _webViewConfigurationApi .setMediaTypesRequiringUserActionForPlaybackForInstances( this, 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 b970ab26bcc7..8bf29308371e 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 @@ -10,52 +10,53 @@ import '../common/web_kit.pigeon.dart'; import '../foundation/foundation.dart'; import 'web_kit.dart'; -Iterable _toWKWebsiteDataTypesEnumData( - Iterable types) { - return types.map((WKWebsiteDataTypes type) { - late final WKWebsiteDataTypesEnum value; +Iterable _toWKWebsiteDataTypeEnumData( + Iterable types) { + return types.map((WKWebsiteDataType type) { + late final WKWebsiteDataTypeEnum value; switch (type) { - case WKWebsiteDataTypes.cookies: - value = WKWebsiteDataTypesEnum.cookies; + case WKWebsiteDataType.cookies: + value = WKWebsiteDataTypeEnum.cookies; break; - case WKWebsiteDataTypes.memoryCache: - value = WKWebsiteDataTypesEnum.memoryCache; + case WKWebsiteDataType.memoryCache: + value = WKWebsiteDataTypeEnum.memoryCache; break; - case WKWebsiteDataTypes.diskCache: - value = WKWebsiteDataTypesEnum.diskCache; + case WKWebsiteDataType.diskCache: + value = WKWebsiteDataTypeEnum.diskCache; break; - case WKWebsiteDataTypes.offlineWebApplicationCache: - value = WKWebsiteDataTypesEnum.offlineWebApplicationCache; + case WKWebsiteDataType.offlineWebApplicationCache: + value = WKWebsiteDataTypeEnum.offlineWebApplicationCache; break; - case WKWebsiteDataTypes.localStroage: - value = WKWebsiteDataTypesEnum.localStroage; + case WKWebsiteDataType.localStorage: + value = WKWebsiteDataTypeEnum.localStorage; break; - case WKWebsiteDataTypes.sessionStorage: - value = WKWebsiteDataTypesEnum.sessionStorage; + case WKWebsiteDataType.sessionStorage: + value = WKWebsiteDataTypeEnum.sessionStorage; break; - case WKWebsiteDataTypes.sqlDatabases: - value = WKWebsiteDataTypesEnum.sqlDatabases; + case WKWebsiteDataType.webSQLDatabases: + value = WKWebsiteDataTypeEnum.webSQLDatabases; break; - case WKWebsiteDataTypes.indexedDBDatabases: - value = WKWebsiteDataTypesEnum.indexedDBDatabases; + case WKWebsiteDataType.indexedDBDatabases: + value = WKWebsiteDataTypeEnum.indexedDBDatabases; break; } - return WKWebsiteDataTypesEnumData(value: value); + return WKWebsiteDataTypeEnumData(value: value); }); } extension _NSHttpCookieConverter on NSHttpCookie { NSHttpCookieData toNSHttpCookieData() { + final Iterable keys = properties.keys; return NSHttpCookieData( - properties: properties.map( - (NSHttpCookiePropertyKey key, Object value) { - return MapEntry( - key.toNSHttpCookiePropertyKeyEnumData(), - value.toString(), - ); + propertyKeys: keys.map( + (NSHttpCookiePropertyKey key) { + return key.toNSHttpCookiePropertyKeyEnumData(); }, - ), + ).toList(), + propertyValues: keys + .map((NSHttpCookiePropertyKey key) => properties[key]!) + .toList(), ); } } @@ -258,12 +259,12 @@ class WKWebsiteDataStoreHostApiImpl extends WKWebsiteDataStoreHostApi { /// Calls [removeDataOfTypes] with the ids of the provided object instances. Future removeDataOfTypesForInstances( WKWebsiteDataStore instance, - Set dataTypes, { + Set dataTypes, { required double secondsModifiedSinceEpoch, }) { return removeDataOfTypes( instanceManager.getInstanceId(instance)!, - _toWKWebsiteDataTypesEnumData(dataTypes).toList(), + _toWKWebsiteDataTypeEnumData(dataTypes).toList(), secondsModifiedSinceEpoch, ); } diff --git a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/web_kit_cookie_manager.dart b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/web_kit_cookie_manager.dart index c73111d73fd0..46322319ae89 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/web_kit_cookie_manager.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/web_kit_cookie_manager.dart @@ -19,7 +19,7 @@ class WebKitCookieManager extends WebViewCookieManagerPlatform { @override Future clearCookies() async { return websiteDataStore.removeDataOfTypes( - {WKWebsiteDataTypes.cookies}, + {WKWebsiteDataType.cookies}, DateTime.fromMillisecondsSinceEpoch(0), ); } diff --git a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/web_kit_webview_widget.dart b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/web_kit_webview_widget.dart index 8c37112d7a24..0a177d854bc2 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/web_kit_webview_widget.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/web_kit_webview_widget.dart @@ -227,11 +227,11 @@ class WebKitWebViewPlatformController extends WebViewPlatformController { @override Future clearCache() { return webView.configuration.websiteDataStore.removeDataOfTypes( - { - WKWebsiteDataTypes.memoryCache, - WKWebsiteDataTypes.diskCache, - WKWebsiteDataTypes.offlineWebApplicationCache, - WKWebsiteDataTypes.localStroage, + { + WKWebsiteDataType.memoryCache, + WKWebsiteDataType.diskCache, + WKWebsiteDataType.offlineWebApplicationCache, + WKWebsiteDataType.localStorage, }, DateTime.fromMillisecondsSinceEpoch(0), ); @@ -517,8 +517,12 @@ class WebKitWebViewPlatformController extends WebViewPlatformController { Set removedJavaScriptChannels = const {}, }) async { webView.configuration.userContentController.removeAllUserScripts(); - webView.configuration.userContentController - .removeAllScriptMessageHandlers(); + // TODO(bparrishMines): This can be replaced with + // `removeAllScriptMessageHandlers` once Dart supports runtime version + // checking. (e.g. The equivalent to @availability in Objective-C.) + _scriptMessageHandlers.keys.forEach( + webView.configuration.userContentController.removeScriptMessageHandler, + ); removedJavaScriptChannels.forEach(_scriptMessageHandlers.remove); final Set remainingNames = _scriptMessageHandlers.keys.toSet(); 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 509fa8e1f7dd..6844a5fa67ad 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/pigeons/web_kit.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/pigeons/web_kit.dart @@ -37,10 +37,10 @@ enum NSKeyValueObservingOptionsEnum { priorNotification, } +// TODO(bparrishMines): Enums need be wrapped in a data class because thay can't +// be used as primitive arguments. See https://github.com/flutter/flutter/issues/87307 class NSKeyValueObservingOptionsEnumData { - // TODO(bparrishMines): Generated code fails when enums are marked as nonnull. - // Change to nonnull once this is fixed: https://github.com/flutter/flutter/issues/100594 - late NSKeyValueObservingOptionsEnum? value; + late NSKeyValueObservingOptionsEnum value; } /// Mirror of NSKeyValueChange. @@ -53,8 +53,10 @@ enum NSKeyValueChangeEnum { replacement, } +// TODO(bparrishMines): Enums need be wrapped in a data class because thay can't +// be used as primitive arguments. See https://github.com/flutter/flutter/issues/87307 class NSKeyValueChangeEnumData { - late NSKeyValueChangeEnum? value; + late NSKeyValueChangeEnum value; } /// Mirror of NSKeyValueChangeKey. @@ -68,8 +70,10 @@ enum NSKeyValueChangeKeyEnum { oldValue, } +// TODO(bparrishMines): Enums need be wrapped in a data class because thay can't +// be used as primitive arguments. See https://github.com/flutter/flutter/issues/87307 class NSKeyValueChangeKeyEnumData { - late NSKeyValueChangeKeyEnum? value; + late NSKeyValueChangeKeyEnum value; } /// Mirror of WKUserScriptInjectionTime. @@ -80,8 +84,10 @@ enum WKUserScriptInjectionTimeEnum { atDocumentEnd, } +// TODO(bparrishMines): Enums need be wrapped in a data class because thay can't +// be used as primitive arguments. See https://github.com/flutter/flutter/issues/87307 class WKUserScriptInjectionTimeEnumData { - late WKUserScriptInjectionTimeEnum? value; + late WKUserScriptInjectionTimeEnum value; } /// Mirror of WKAudiovisualMediaTypes. @@ -94,26 +100,30 @@ enum WKAudiovisualMediaTypeEnum { all, } +// TODO(bparrishMines): Enums need be wrapped in a data class because thay can't +// be used as primitive arguments. See https://github.com/flutter/flutter/issues/87307 class WKAudiovisualMediaTypeEnumData { - late WKAudiovisualMediaTypeEnum? value; + late WKAudiovisualMediaTypeEnum value; } /// Mirror of WKWebsiteDataTypes. /// /// See https://developer.apple.com/documentation/webkit/wkwebsitedatarecord/data_store_record_types?language=objc. -enum WKWebsiteDataTypesEnum { +enum WKWebsiteDataTypeEnum { cookies, memoryCache, diskCache, offlineWebApplicationCache, - localStroage, + localStorage, sessionStorage, - sqlDatabases, + webSQLDatabases, indexedDBDatabases, } -class WKWebsiteDataTypesEnumData { - late WKWebsiteDataTypesEnum? value; +// TODO(bparrishMines): Enums need be wrapped in a data class because thay can't +// be used as primitive arguments. See https://github.com/flutter/flutter/issues/87307 +class WKWebsiteDataTypeEnumData { + late WKWebsiteDataTypeEnum value; } /// Mirror of WKNavigationActionPolicy. @@ -124,8 +134,10 @@ enum WKNavigationActionPolicyEnum { cancel, } +// TODO(bparrishMines): Enums need be wrapped in a data class because thay can't +// be used as primitive arguments. See https://github.com/flutter/flutter/issues/87307 class WKNavigationActionPolicyEnumData { - late WKNavigationActionPolicyEnum? value; + late WKNavigationActionPolicyEnum value; } /// Mirror of NSHTTPCookiePropertyKey. @@ -148,8 +160,10 @@ enum NSHttpCookiePropertyKeyEnum { version, } +// TODO(bparrishMines): Enums need be wrapped in a data class because thay can't +// be used as primitive arguments. See https://github.com/flutter/flutter/issues/87307 class NSHttpCookiePropertyKeyEnumData { - late NSHttpCookiePropertyKeyEnum? value; + late NSHttpCookiePropertyKeyEnum value; } /// Mirror of NSURLRequest. @@ -207,7 +221,13 @@ class WKScriptMessageData { /// /// See https://developer.apple.com/documentation/foundation/nshttpcookie?language=objc. class NSHttpCookieData { - late Map properties; + // TODO(bparrishMines): Change to a map when Objective-C data classes conform + // to `NSCopying`. See https://github.com/flutter/flutter/issues/103383. + // `NSDictionary`s are unable to use data classes as keys because they don't + // conform to `NSCopying`. This splits the map of properties into a list of + // keys and values with the ordered maintained. + late List propertyKeys; + late List propertyValues; } /// Mirror of WKWebsiteDataStore. @@ -216,7 +236,7 @@ class NSHttpCookieData { @HostApi(dartHostTestHandler: 'TestWKWebsiteDataStoreHostApi') abstract class WKWebsiteDataStoreHostApi { @ObjCSelector( - 'createDataStoreFromConfigurationWithIdentifier:configurationIdentifier:', + 'createFromWebViewConfigurationWithIdentifier:configurationIdentifier:', ) void createFromWebViewConfiguration( int instanceId, @@ -227,13 +247,13 @@ abstract class WKWebsiteDataStoreHostApi { void createDefaultDataStore(int instanceId); @ObjCSelector( - 'removeDataFromDataStoreWithIdentifier:ofTypes:secondsModifiedSinceEpoch:', + 'removeDataFromDataStoreWithIdentifier:ofTypes:modifiedSince:', ) @async bool removeDataOfTypes( int instanceId, - List dataTypes, - double secondsModifiedSinceEpoch, + List dataTypes, + double modificationTimeInSecondsSinceEpoch, ); } @@ -242,9 +262,6 @@ abstract class WKWebsiteDataStoreHostApi { /// See https://developer.apple.com/documentation/uikit/uiview?language=objc. @HostApi(dartHostTestHandler: 'TestUIViewHostApi') abstract class UIViewHostApi { - @ObjCSelector('contentOffsetForViewWithIdentifier:') - List getContentOffset(int instanceId); - @ObjCSelector('setBackgroundColorForViewWithIdentifier:toValue:') void setBackgroundColor(int instanceId, int? value); @@ -263,7 +280,7 @@ abstract class UIScrollViewHostApi { @ObjCSelector('contentOffsetForScrollViewWithIdentifier:') List getContentOffset(int instanceId); - @ObjCSelector('scrollByForScrollViewWithIdentifier:toX:y:') + @ObjCSelector('scrollByForScrollViewWithIdentifier:x:y:') void scrollBy(int instanceId, double x, double y); @ObjCSelector('setContentOffsetForScrollViewWithIdentifier:toX:y:') @@ -282,7 +299,7 @@ abstract class WKWebViewConfigurationHostApi { void createFromWebView(int instanceId, int webViewInstanceId); @ObjCSelector( - 'setAllowsInlineMediaPlaybackForConfigurationWithIdentifier:isAlowed:', + 'setAllowsInlineMediaPlaybackForConfigurationWithIdentifier:isAllowed:', ) void setAllowsInlineMediaPlayback(int instanceId, bool allow); @@ -335,7 +352,9 @@ abstract class WKUserContentControllerHostApi { /// See https://developer.apple.com/documentation/webkit/wkpreferences?language=objc. @HostApi(dartHostTestHandler: 'TestWKPreferencesHostApi') abstract class WKPreferencesHostApi { - @ObjCSelector('createFromWebViewConfiguration:configurationIdentifier:') + @ObjCSelector( + 'createFromWebViewConfigurationWithIdentifier:configurationIdentifier:', + ) void createFromWebViewConfiguration( int instanceId, int configurationInstanceId, @@ -498,5 +517,6 @@ abstract class WKHttpCookieStoreHostApi { ); @ObjCSelector('setCookieForStoreWithIdentifier:cookie:') + @async void setCookie(int instanceId, NSHttpCookieData cookie); } diff --git a/packages/webview_flutter/webview_flutter_wkwebview/test/src/common/test_web_kit.pigeon.dart b/packages/webview_flutter/webview_flutter_wkwebview/test/src/common/test_web_kit.pigeon.dart index 042ddedbd769..1f963b4d9bc3 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/test/src/common/test_web_kit.pigeon.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/test/src/common/test_web_kit.pigeon.dart @@ -18,7 +18,7 @@ class _TestWKWebsiteDataStoreHostApiCodec extends StandardMessageCodec { const _TestWKWebsiteDataStoreHostApiCodec(); @override void writeValue(WriteBuffer buffer, Object? value) { - if (value is WKWebsiteDataTypesEnumData) { + if (value is WKWebsiteDataTypeEnumData) { buffer.putUint8(128); writeValue(buffer, value.encode()); } else { @@ -30,7 +30,7 @@ class _TestWKWebsiteDataStoreHostApiCodec extends StandardMessageCodec { Object? readValueOfType(int type, ReadBuffer buffer) { switch (type) { case 128: - return WKWebsiteDataTypesEnumData.decode(readValue(buffer)!); + return WKWebsiteDataTypeEnumData.decode(readValue(buffer)!); default: return super.readValueOfType(type, buffer); @@ -47,8 +47,8 @@ abstract class TestWKWebsiteDataStoreHostApi { void createDefaultDataStore(int instanceId); Future removeDataOfTypes( int instanceId, - List dataTypes, - double secondsModifiedSinceEpoch); + List dataTypes, + double modificationTimeInSecondsSinceEpoch); static void setup(TestWKWebsiteDataStoreHostApi? api, {BinaryMessenger? binaryMessenger}) { { @@ -110,15 +110,16 @@ abstract class TestWKWebsiteDataStoreHostApi { final int? arg_instanceId = (args[0] as int?); assert(arg_instanceId != null, 'Argument for dev.flutter.pigeon.WKWebsiteDataStoreHostApi.removeDataOfTypes was null, expected non-null int.'); - final List? arg_dataTypes = - (args[1] as List?)?.cast(); + final List? arg_dataTypes = + (args[1] as List?)?.cast(); assert(arg_dataTypes != null, - 'Argument for dev.flutter.pigeon.WKWebsiteDataStoreHostApi.removeDataOfTypes was null, expected non-null List.'); - final double? arg_secondsModifiedSinceEpoch = (args[2] as double?); - assert(arg_secondsModifiedSinceEpoch != null, + 'Argument for dev.flutter.pigeon.WKWebsiteDataStoreHostApi.removeDataOfTypes was null, expected non-null List.'); + final double? arg_modificationTimeInSecondsSinceEpoch = + (args[2] as double?); + assert(arg_modificationTimeInSecondsSinceEpoch != null, 'Argument for dev.flutter.pigeon.WKWebsiteDataStoreHostApi.removeDataOfTypes was null, expected non-null double.'); - final bool output = await api.removeDataOfTypes( - arg_instanceId!, arg_dataTypes!, arg_secondsModifiedSinceEpoch!); + final bool output = await api.removeDataOfTypes(arg_instanceId!, + arg_dataTypes!, arg_modificationTimeInSecondsSinceEpoch!); return {'result': output}; }); } @@ -133,30 +134,10 @@ class _TestUIViewHostApiCodec extends StandardMessageCodec { abstract class TestUIViewHostApi { static const MessageCodec codec = _TestUIViewHostApiCodec(); - List getContentOffset(int instanceId); void setBackgroundColor(int instanceId, int? value); void setOpaque(int instanceId, bool opaque); static void setup(TestUIViewHostApi? api, {BinaryMessenger? binaryMessenger}) { - { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.UIViewHostApi.getContentOffset', codec, - binaryMessenger: binaryMessenger); - if (api == null) { - channel.setMockMessageHandler(null); - } else { - channel.setMockMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.UIViewHostApi.getContentOffset was null.'); - final List args = (message as List?)!; - final int? arg_instanceId = (args[0] as int?); - assert(arg_instanceId != null, - 'Argument for dev.flutter.pigeon.UIViewHostApi.getContentOffset was null, expected non-null int.'); - final List output = api.getContentOffset(arg_instanceId!); - return {'result': output}; - }); - } - } { final BasicMessageChannel channel = BasicMessageChannel( 'dev.flutter.pigeon.UIViewHostApi.setBackgroundColor', codec, @@ -909,7 +890,7 @@ class _TestWKWebViewHostApiCodec extends StandardMessageCodec { } else if (value is WKUserScriptInjectionTimeEnumData) { buffer.putUint8(134); writeValue(buffer, value.encode()); - } else if (value is WKWebsiteDataTypesEnumData) { + } else if (value is WKWebsiteDataTypeEnumData) { buffer.putUint8(135); writeValue(buffer, value.encode()); } else { @@ -942,7 +923,7 @@ class _TestWKWebViewHostApiCodec extends StandardMessageCodec { return WKUserScriptInjectionTimeEnumData.decode(readValue(buffer)!); case 135: - return WKWebsiteDataTypesEnumData.decode(readValue(buffer)!); + return WKWebsiteDataTypeEnumData.decode(readValue(buffer)!); default: return super.readValueOfType(type, buffer); @@ -1418,7 +1399,7 @@ abstract class TestWKHttpCookieStoreHostApi { void createFromWebsiteDataStore( int instanceId, int websiteDataStoreInstanceId); - void setCookie(int instanceId, NSHttpCookieData cookie); + Future setCookie(int instanceId, NSHttpCookieData cookie); static void setup(TestWKHttpCookieStoreHostApi? api, {BinaryMessenger? binaryMessenger}) { { @@ -1462,7 +1443,7 @@ abstract class TestWKHttpCookieStoreHostApi { final NSHttpCookieData? arg_cookie = (args[1] as NSHttpCookieData?); assert(arg_cookie != null, 'Argument for dev.flutter.pigeon.WKHttpCookieStoreHostApi.setCookie was null, expected non-null NSHttpCookieData.'); - api.setCookie(arg_instanceId!, arg_cookie!); + await api.setCookie(arg_instanceId!, arg_cookie!); return {}; }); } diff --git a/packages/webview_flutter/webview_flutter_wkwebview/test/src/ui_kit/ui_kit_test.mocks.dart b/packages/webview_flutter/webview_flutter_wkwebview/test/src/ui_kit/ui_kit_test.mocks.dart index 908709c90134..a9f9b2c322c7 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/test/src/ui_kit/ui_kit_test.mocks.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/test/src/ui_kit/ui_kit_test.mocks.dart @@ -185,10 +185,6 @@ class MockTestUIViewHostApi extends _i1.Mock implements _i2.TestUIViewHostApi { _i1.throwOnMissingStub(this); } - @override - List getContentOffset(int? instanceId) => - (super.noSuchMethod(Invocation.method(#getContentOffset, [instanceId]), - returnValue: []) as List); @override void setBackgroundColor(int? instanceId, int? value) => super.noSuchMethod( Invocation.method(#setBackgroundColor, [instanceId, value]), 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 8564bf889c2f..ae13ca9e6b6d 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 @@ -95,21 +95,21 @@ void main() { expect( websiteDataStore.removeDataOfTypes( - {WKWebsiteDataTypes.cookies}, + {WKWebsiteDataType.cookies}, DateTime.fromMillisecondsSinceEpoch(5000), ), completion(true), ); - final List typeData = + final List typeData = verify(mockPlatformHostApi.removeDataOfTypes( instanceManager.getInstanceId(websiteDataStore), captureAny, 5.0, - )).captured.single.cast() - as List; + )).captured.single.cast() + as List; - expect(typeData.single.value, WKWebsiteDataTypesEnum.cookies); + expect(typeData.single.value, WKWebsiteDataTypeEnum.cookies); }); }); @@ -169,10 +169,10 @@ void main() { ).captured.single as NSHttpCookieData; expect( - cookie.properties.entries.single.key!.value, + cookie.propertyKeys.single!.value, NSHttpCookiePropertyKeyEnum.comment, ); - expect(cookie.properties.entries.single.value, 'aComment'); + expect(cookie.propertyValues.single, 'aComment'); }); }); diff --git a/packages/webview_flutter/webview_flutter_wkwebview/test/src/web_kit/web_kit_test.mocks.dart b/packages/webview_flutter/webview_flutter_wkwebview/test/src/web_kit/web_kit_test.mocks.dart index d4f1fefc190c..4ffb7d4c19d3 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/test/src/web_kit/web_kit_test.mocks.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/test/src/web_kit/web_kit_test.mocks.dart @@ -2,11 +2,11 @@ // in webview_flutter_wkwebview/example/ios/.symlinks/plugins/webview_flutter_wkwebview/test/src/web_kit/web_kit_test.dart. // Do not manually edit this file. -import 'dart:async' as _i4; +import 'dart:async' as _i3; import 'package:mockito/mockito.dart' as _i1; import 'package:webview_flutter_wkwebview/src/common/web_kit.pigeon.dart' - as _i3; + as _i4; import '../common/test_web_kit.pigeon.dart' as _i2; @@ -37,9 +37,10 @@ class MockTestWKHttpCookieStoreHostApi extends _i1.Mock [instanceId, websiteDataStoreInstanceId]), returnValueForMissingStub: null); @override - void setCookie(int? instanceId, _i3.NSHttpCookieData? cookie) => - super.noSuchMethod(Invocation.method(#setCookie, [instanceId, cookie]), - returnValueForMissingStub: null); + _i3.Future setCookie(int? instanceId, _i4.NSHttpCookieData? cookie) => + (super.noSuchMethod(Invocation.method(#setCookie, [instanceId, cookie]), + returnValue: Future.value(), + returnValueForMissingStub: Future.value()) as _i3.Future); } /// A class which mocks [TestWKNavigationDelegateHostApi]. @@ -149,7 +150,7 @@ class MockTestWKUserContentControllerHostApi extends _i1.Mock Invocation.method(#removeAllScriptMessageHandlers, [instanceId]), returnValueForMissingStub: null); @override - void addUserScript(int? instanceId, _i3.WKUserScriptData? userScript) => super + void addUserScript(int? instanceId, _i4.WKUserScriptData? userScript) => super .noSuchMethod(Invocation.method(#addUserScript, [instanceId, userScript]), returnValueForMissingStub: null); @override @@ -184,7 +185,7 @@ class MockTestWKWebViewConfigurationHostApi extends _i1.Mock returnValueForMissingStub: null); @override void setMediaTypesRequiringUserActionForPlayback( - int? instanceId, List<_i3.WKAudiovisualMediaTypeEnumData?>? types) => + int? instanceId, List<_i4.WKAudiovisualMediaTypeEnumData?>? types) => super.noSuchMethod( Invocation.method(#setMediaTypesRequiringUserActionForPlayback, [instanceId, types]), @@ -225,7 +226,7 @@ class MockTestWKWebViewHostApi extends _i1.Mock Invocation.method(#getEstimatedProgress, [instanceId]), returnValue: 0.0) as double); @override - void loadRequest(int? instanceId, _i3.NSUrlRequestData? request) => + void loadRequest(int? instanceId, _i4.NSUrlRequestData? request) => super.noSuchMethod(Invocation.method(#loadRequest, [instanceId, request]), returnValueForMissingStub: null); @override @@ -278,12 +279,12 @@ class MockTestWKWebViewHostApi extends _i1.Mock Invocation.method(#setCustomUserAgent, [instanceId, userAgent]), returnValueForMissingStub: null); @override - _i4.Future evaluateJavaScript( + _i3.Future evaluateJavaScript( int? instanceId, String? javaScriptString) => (super.noSuchMethod( Invocation.method( #evaluateJavaScript, [instanceId, javaScriptString]), - returnValue: Future.value()) as _i4.Future); + returnValue: Future.value()) as _i3.Future); } /// A class which mocks [TestWKWebsiteDataStoreHostApi]. @@ -307,12 +308,12 @@ class MockTestWKWebsiteDataStoreHostApi extends _i1.Mock Invocation.method(#createDefaultDataStore, [instanceId]), returnValueForMissingStub: null); @override - _i4.Future removeDataOfTypes( + _i3.Future removeDataOfTypes( int? instanceId, - List<_i3.WKWebsiteDataTypesEnumData?>? dataTypes, + List<_i4.WKWebsiteDataTypeEnumData?>? dataTypes, double? secondsModifiedSinceEpoch) => (super.noSuchMethod( Invocation.method(#removeDataOfTypes, [instanceId, dataTypes, secondsModifiedSinceEpoch]), - returnValue: Future.value(false)) as _i4.Future); + returnValue: Future.value(false)) as _i3.Future); } diff --git a/packages/webview_flutter/webview_flutter_wkwebview/test/src/web_kit_cookie_manager_test.dart b/packages/webview_flutter/webview_flutter_wkwebview/test/src/web_kit_cookie_manager_test.dart index 8f23ff6b4a3d..6baff12eda17 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/test/src/web_kit_cookie_manager_test.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/test/src/web_kit_cookie_manager_test.dart @@ -37,12 +37,12 @@ void main() { test('clearCookies', () async { when(mockWebsiteDataStore.removeDataOfTypes( - {WKWebsiteDataTypes.cookies}, any)) + {WKWebsiteDataType.cookies}, any)) .thenAnswer((_) => Future.value(true)); expect(cookieManager.clearCookies(), completion(true)); when(mockWebsiteDataStore.removeDataOfTypes( - {WKWebsiteDataTypes.cookies}, any)) + {WKWebsiteDataType.cookies}, any)) .thenAnswer((_) => Future.value(false)); expect(cookieManager.clearCookies(), completion(false)); }); diff --git a/packages/webview_flutter/webview_flutter_wkwebview/test/src/web_kit_cookie_manager_test.mocks.dart b/packages/webview_flutter/webview_flutter_wkwebview/test/src/web_kit_cookie_manager_test.mocks.dart index a85c57f7bdb3..8d7751da785f 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/test/src/web_kit_cookie_manager_test.mocks.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/test/src/web_kit_cookie_manager_test.mocks.dart @@ -79,7 +79,7 @@ class MockWKWebsiteDataStore extends _i1.Mock returnValue: _FakeWKHttpCookieStore_0()) as _i2.WKHttpCookieStore); @override _i3.Future removeDataOfTypes( - Set<_i2.WKWebsiteDataTypes>? dataTypes, DateTime? since) => + Set<_i2.WKWebsiteDataType>? dataTypes, DateTime? since) => (super.noSuchMethod( Invocation.method(#removeDataOfTypes, [dataTypes, since]), returnValue: Future.value(false)) as _i3.Future); diff --git a/packages/webview_flutter/webview_flutter_wkwebview/test/src/web_kit_webview_widget_test.dart b/packages/webview_flutter/webview_flutter_wkwebview/test/src/web_kit_webview_widget_test.dart index e5042dab78e4..d77feee22dd1 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/test/src/web_kit_webview_widget_test.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/test/src/web_kit_webview_widget_test.dart @@ -330,7 +330,7 @@ void main() { final List javaScriptChannels = verifyInOrder([ mockUserContentController.removeAllUserScripts(), - mockUserContentController.removeAllScriptMessageHandlers(), + mockUserContentController.removeScriptMessageHandler('myChannel'), mockUserContentController.addScriptMessageHandler( captureAny, captureAny, @@ -372,7 +372,6 @@ void main() { )); verify(mockUserContentController.removeAllUserScripts()); - verify(mockUserContentController.removeAllScriptMessageHandlers()); verifyNever(mockUserContentController.addScriptMessageHandler( any, any, @@ -769,11 +768,11 @@ void main() { await buildWidget(tester); when( mockWebsiteDataStore.removeDataOfTypes( - { - WKWebsiteDataTypes.memoryCache, - WKWebsiteDataTypes.diskCache, - WKWebsiteDataTypes.offlineWebApplicationCache, - WKWebsiteDataTypes.localStroage, + { + WKWebsiteDataType.memoryCache, + WKWebsiteDataType.diskCache, + WKWebsiteDataType.offlineWebApplicationCache, + WKWebsiteDataType.localStorage, }, DateTime.fromMillisecondsSinceEpoch(0), ), @@ -835,12 +834,15 @@ void main() { await testController.removeJavascriptChannels({'c'}); - verify(mockUserContentController.removeAllScriptMessageHandlers()); verify(mockUserContentController.removeAllUserScripts()); + verify(mockUserContentController.removeScriptMessageHandler('c')); + verify(mockUserContentController.removeScriptMessageHandler('d')); final List javaScriptChannels = verify( mockUserContentController.addScriptMessageHandler( - captureAny, captureAny), + captureAny, + captureAny, + ), ).captured; expect( javaScriptChannels[0], diff --git a/packages/webview_flutter/webview_flutter_wkwebview/test/src/web_kit_webview_widget_test.mocks.dart b/packages/webview_flutter/webview_flutter_wkwebview/test/src/web_kit_webview_widget_test.mocks.dart index 1138d13f0c25..066f33a9774e 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/test/src/web_kit_webview_widget_test.mocks.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/test/src/web_kit_webview_widget_test.mocks.dart @@ -434,7 +434,7 @@ class MockWKWebsiteDataStore extends _i1.Mock returnValue: _FakeWKHttpCookieStore_6()) as _i3.WKHttpCookieStore); @override _i5.Future removeDataOfTypes( - Set<_i3.WKWebsiteDataTypes>? dataTypes, DateTime? since) => + Set<_i3.WKWebsiteDataType>? dataTypes, DateTime? since) => (super.noSuchMethod( Invocation.method(#removeDataOfTypes, [dataTypes, since]), returnValue: Future.value(false)) as _i5.Future);