Skip to content

Commit 4d2d2e3

Browse files
[webview] Add macOS support in implementation package (#6221)
Adds initial support for macOS. Known limitations: - Scroll APIs are not supported, and currently throw unimplemented. Longer term we could consider JS polyfills, but we'd probably want to make them opt-in since injecting JS into every page has some risks. - Setting the background color doesn't work since the view structure is different on macOS. We may be able to use a layer-backed view to support this in the future. Since many use cases don't require these features, my preference is to land this without that support, rather than blocking on having full parity, and then the specific features can be added later based on community interest (demand and/or contributions). This requires 3.24, as 3.22 does not yet have gesture support for macOS platform views, and pushing this to users without gesture support would be very confusing. Part of flutter/flutter#41725
1 parent 584eee3 commit 4d2d2e3

File tree

130 files changed

+5765
-2352
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

130 files changed

+5765
-2352
lines changed

packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
## NEXT
1+
## 3.15.0
22

3-
* Updates minimum supported SDK version to Flutter 3.19/Dart 3.3.
3+
* Adds macOS support.
44

55
## 3.14.0
66

@@ -92,7 +92,7 @@
9292

9393
* Introduces `NSError.toString` for better diagnostics.
9494

95-
## 3.6.2
95+
## 3.6.2
9696

9797
* Fixes unawaited_futures violations.
9898

+12-7
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,15 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44

5-
@import Flutter;
65
@import XCTest;
76
@import webview_flutter_wkwebview;
87

8+
#if TARGET_OS_OSX
9+
@import FlutterMacOS;
10+
#else
11+
@import Flutter;
12+
#endif
13+
914
#import <OCMock/OCMock.h>
1015

1116
@interface FWFDataConvertersTests : XCTestCase
@@ -61,8 +66,8 @@ - (void)testFWFWKNavigationActionDataFromNavigationAction {
6166

6267
OCMStub([mockNavigationAction navigationType]).andReturn(WKNavigationTypeReload);
6368

64-
NSURLRequest *request =
65-
[NSURLRequest requestWithURL:[NSURL URLWithString:@"https://www.flutter.dev/"]];
69+
NSURL *testURL = [NSURL URLWithString:@"https://www.flutter.dev/"];
70+
NSURLRequest *request = [NSURLRequest requestWithURL:testURL];
6671
OCMStub([mockNavigationAction request]).andReturn(request);
6772

6873
WKFrameInfo *mockFrameInfo = OCMClassMock([WKFrameInfo class]);
@@ -76,8 +81,8 @@ - (void)testFWFWKNavigationActionDataFromNavigationAction {
7681
}
7782

7883
- (void)testFWFNSUrlRequestDataFromNSURLRequest {
79-
NSMutableURLRequest *request =
80-
[NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"https://www.flutter.dev/"]];
84+
NSURL *testURL = [NSURL URLWithString:@"https://www.flutter.dev/"];
85+
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:testURL];
8186
request.HTTPMethod = @"POST";
8287
request.HTTPBody = [@"aString" dataUsingEncoding:NSUTF8StringEncoding];
8388
request.allHTTPHeaderFields = @{@"a" : @"field"};
@@ -137,7 +142,7 @@ - (void)testFWFWKSecurityOriginDataFromWKSecurityOrigin {
137142
XCTAssertEqualObjects(data.protocol, @"protocol");
138143
}
139144

140-
- (void)testFWFWKPermissionDecisionFromData API_AVAILABLE(ios(15.0)) {
145+
- (void)testFWFWKPermissionDecisionFromData API_AVAILABLE(ios(15.0), macos(12)) {
141146
XCTAssertEqual(FWFNativeWKPermissionDecisionFromData(
142147
[FWFWKPermissionDecisionData makeWithValue:FWFWKPermissionDecisionDeny]),
143148
WKPermissionDecisionDeny);
@@ -149,7 +154,7 @@ - (void)testFWFWKPermissionDecisionFromData API_AVAILABLE(ios(15.0)) {
149154
WKPermissionDecisionPrompt);
150155
}
151156

152-
- (void)testFWFWKMediaCaptureTypeDataFromWKMediaCaptureType API_AVAILABLE(ios(15.0)) {
157+
- (void)testFWFWKMediaCaptureTypeDataFromWKMediaCaptureType API_AVAILABLE(ios(15.0), macos(12)) {
153158
XCTAssertEqual(
154159
FWFWKMediaCaptureTypeDataFromNativeWKMediaCaptureType(WKMediaCaptureTypeCamera).value,
155160
FWFWKMediaCaptureTypeCamera);
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,15 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44

5-
@import Flutter;
65
@import XCTest;
76
@import webview_flutter_wkwebview;
87

8+
#if TARGET_OS_OSX
9+
@import FlutterMacOS;
10+
#else
11+
@import Flutter;
12+
#endif
13+
914
#import <OCMock/OCMock.h>
1015

1116
@interface FWFHTTPCookieStoreHostApiTests : XCTestCase
@@ -47,9 +52,8 @@ - (void)testSetCookie {
4752
completion:^(FlutterError *error) {
4853
blockError = error;
4954
}];
50-
OCMVerify([mockHttpCookieStore
51-
setCookie:[NSHTTPCookie cookieWithProperties:@{NSHTTPCookieName : @"hello"}]
52-
completionHandler:OCMOCK_ANY]);
55+
NSHTTPCookie *cookie = [NSHTTPCookie cookieWithProperties:@{NSHTTPCookieName : @"hello"}];
56+
OCMVerify([mockHttpCookieStore setCookie:cookie completionHandler:OCMOCK_ANY]);
5357
XCTAssertNil(blockError);
5458
}
5559
@end
+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44

5-
#import <XCTest/XCTest.h>
5+
@import XCTest;
66

77
@import webview_flutter_wkwebview;
88
#if __has_include(<webview_flutter_wkwebview/webview-umbrella.h>)
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,15 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44

5-
@import Flutter;
65
@import XCTest;
76
@import webview_flutter_wkwebview;
87

8+
#if TARGET_OS_OSX
9+
@import FlutterMacOS;
10+
#else
11+
@import Flutter;
12+
#endif
13+
914
#import <OCMock/OCMock.h>
1015

1116
@interface FWFNavigationDelegateHostApiTests : XCTestCase
@@ -117,8 +122,8 @@ - (void)testDecidePolicyForNavigationAction {
117122
[instanceManager addDartCreatedInstance:mockWebView withIdentifier:1];
118123

119124
WKNavigationAction *mockNavigationAction = OCMClassMock([WKNavigationAction class]);
120-
OCMStub([mockNavigationAction request])
121-
.andReturn([NSURLRequest requestWithURL:[NSURL URLWithString:@"https://www.flutter.dev"]]);
125+
NSURL *testURL = [NSURL URLWithString:@"https://www.flutter.dev"];
126+
OCMStub([mockNavigationAction request]).andReturn([NSURLRequest requestWithURL:testURL]);
122127

123128
WKFrameInfo *mockFrameInfo = OCMClassMock([WKFrameInfo class]);
124129
OCMStub([mockFrameInfo isMainFrame]).andReturn(YES);
@@ -258,10 +263,10 @@ - (void)testDidReceiveAuthenticationChallenge {
258263
NSURLCredential *__block callbackCredential;
259264
[mockDelegate webView:mockWebView
260265
didReceiveAuthenticationChallenge:mockChallenge
261-
completionHandler:^(NSURLSessionAuthChallengeDisposition disposition,
262-
NSURLCredential *credential) {
263-
callbackDisposition = disposition;
264-
callbackCredential = credential;
266+
completionHandler:^(NSURLSessionAuthChallengeDisposition dispositionArg,
267+
NSURLCredential *credentialArg) {
268+
callbackDisposition = dispositionArg;
269+
callbackCredential = credentialArg;
265270
}];
266271

267272
XCTAssertEqual(callbackDisposition, NSURLSessionAuthChallengeCancelAuthenticationChallenge);
+14-5
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,15 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44

5-
@import Flutter;
65
@import XCTest;
76
@import webview_flutter_wkwebview;
87

8+
#if TARGET_OS_OSX
9+
@import FlutterMacOS;
10+
#else
11+
@import Flutter;
12+
#endif
13+
914
#import <OCMock/OCMock.h>
1015

1116
@interface FWFObjectHostApiTests : XCTestCase
@@ -139,8 +144,10 @@ - (void)testObserveValueForKeyPath {
139144
return value[0].value == FWFNSKeyValueChangeKeyEnumOldValue;
140145
}]
141146
changeValues:[OCMArg checkWithBlock:^BOOL(id value) {
142-
FWFObjectOrIdentifier *object = (FWFObjectOrIdentifier *)value[0];
143-
return !object.isIdentifier && [@"key" isEqual:object.value];
147+
FWFObjectOrIdentifier *changeObject =
148+
(FWFObjectOrIdentifier *)value[0];
149+
return !changeObject.isIdentifier &&
150+
[@"key" isEqual:changeObject.value];
144151
}]
145152
completion:OCMOCK_ANY]);
146153
}
@@ -173,8 +180,10 @@ - (void)testObserveValueForKeyPathWithIdentifier {
173180
return value[0].value == FWFNSKeyValueChangeKeyEnumOldValue;
174181
}]
175182
changeValues:[OCMArg checkWithBlock:^BOOL(id value) {
176-
FWFObjectOrIdentifier *object = (FWFObjectOrIdentifier *)value[0];
177-
return object.isIdentifier && [@(2) isEqual:object.value];
183+
FWFObjectOrIdentifier *changeObject =
184+
(FWFObjectOrIdentifier *)value[0];
185+
return changeObject.isIdentifier &&
186+
[@(2) isEqual:changeObject.value];
178187
}]
179188
completion:OCMOCK_ANY]);
180189
}
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,15 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44

5-
@import Flutter;
65
@import XCTest;
76
@import webview_flutter_wkwebview;
87

8+
#if TARGET_OS_OSX
9+
@import FlutterMacOS;
10+
#else
11+
@import Flutter;
12+
#endif
13+
914
#import <OCMock/OCMock.h>
1015

1116
@interface FWFPreferencesHostApiTests : XCTestCase
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,15 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44

5-
@import Flutter;
65
@import XCTest;
76
@import webview_flutter_wkwebview;
87

8+
#if TARGET_OS_OSX
9+
@import FlutterMacOS;
10+
#else
11+
@import Flutter;
12+
#endif
13+
914
#import <OCMock/OCMock.h>
1015

1116
@interface FWFScriptMessageHandlerHostApiTests : XCTestCase
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44

5+
#include "TargetConditionals.h"
6+
7+
// The scroll view delegate does not exist on macOS.
8+
#if !TARGET_OS_OSX
9+
510
@import Flutter;
611
@import XCTest;
712
@import webview_flutter_wkwebview;
@@ -80,3 +85,5 @@ - (void)testOnScrollViewDidScrollForDelegateWithIdentifier {
8085
completion:OCMOCK_ANY]);
8186
}
8287
@end
88+
89+
#endif // !TARGET_OS_OSX
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44

5+
#import "TargetConditionals.h"
6+
7+
// Scroll view APIs do not existing on macOS.
8+
#if !TARGET_OS_OSX
9+
510
@import Flutter;
611
@import XCTest;
712
@import webview_flutter_wkwebview;
@@ -79,3 +84,5 @@ - (void)testSetDelegateForScrollView {
7984
XCTAssertNil(error);
8085
}
8186
@end
87+
88+
#endif // !TARGET_OS_OSX
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,18 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44

5-
@import Flutter;
65
@import XCTest;
76
@import webview_flutter_wkwebview;
87
#if __has_include(<webview_flutter_wkwebview/webview-umbrella.h>)
98
@import webview_flutter_wkwebview.Test;
109
#endif
1110

11+
#if TARGET_OS_OSX
12+
@import FlutterMacOS;
13+
#else
14+
@import Flutter;
15+
#endif
16+
1217
#import <OCMock/OCMock.h>
1318

1419
@interface FWFUIDelegateHostApiTests : XCTestCase
@@ -77,8 +82,8 @@ - (void)testOnCreateWebViewForDelegateWithIdentifier {
7782
.ignoringNonObjectArgs();
7883

7984
WKNavigationAction *mockNavigationAction = OCMClassMock([WKNavigationAction class]);
80-
OCMStub([mockNavigationAction request])
81-
.andReturn([NSURLRequest requestWithURL:[NSURL URLWithString:@"https://www.flutter.dev"]]);
85+
NSURL *testURL = [NSURL URLWithString:@"https://www.flutter.dev"];
86+
OCMStub([mockNavigationAction request]).andReturn([NSURLRequest requestWithURL:testURL]);
8287

8388
WKFrameInfo *mockFrameInfo = OCMClassMock([WKFrameInfo class]);
8489
OCMStub([mockFrameInfo isMainFrame]).andReturn(YES);
@@ -100,7 +105,7 @@ - (void)testOnCreateWebViewForDelegateWithIdentifier {
100105
completion:OCMOCK_ANY]);
101106
}
102107

103-
- (void)testRequestMediaCapturePermissionForOrigin API_AVAILABLE(ios(15.0)) {
108+
- (void)testRequestMediaCapturePermissionForOrigin API_AVAILABLE(ios(15.0), macos(12)) {
104109
FWFInstanceManager *instanceManager = [[FWFInstanceManager alloc] init];
105110

106111
FWFUIDelegate *mockDelegate = [self mockDelegateWithManager:instanceManager identifier:0];
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44

5+
#import "TargetConditionals.h"
6+
7+
#if !TARGET_OS_OSX
8+
59
@import Flutter;
610
@import XCTest;
711
@import webview_flutter_wkwebview;
@@ -47,3 +51,5 @@ - (void)testSetOpaque {
4751
}
4852

4953
@end
54+
55+
#endif // !TARGET_OS_OSX
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,15 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44

5-
@import Flutter;
65
@import XCTest;
76
@import webview_flutter_wkwebview;
87

8+
#if TARGET_OS_OSX
9+
@import FlutterMacOS;
10+
#else
11+
@import Flutter;
12+
#endif
13+
914
#import <OCMock/OCMock.h>
1015

1116
@interface FWFURLAuthenticationChallengeHostApiTests : XCTestCase
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,15 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44

5-
@import Flutter;
65
@import XCTest;
76
@import webview_flutter_wkwebview;
87

8+
#if TARGET_OS_OSX
9+
@import FlutterMacOS;
10+
#else
11+
@import Flutter;
12+
#endif
13+
914
#import <OCMock/OCMock.h>
1015

1116
@interface FWFURLCredentialHostApiTests : XCTestCase
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,15 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44

5-
@import Flutter;
65
@import XCTest;
76
@import webview_flutter_wkwebview;
87

8+
#if TARGET_OS_OSX
9+
@import FlutterMacOS;
10+
#else
11+
@import Flutter;
12+
#endif
13+
914
#import <OCMock/OCMock.h>
1015

1116
@interface FWFURLProtectionSpaceHostApiTests : XCTestCase

packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerTests/FWFURLTests.m renamed to packages/webview_flutter/webview_flutter_wkwebview/darwin/Tests/FWFURLTests.m

+6-1
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,15 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44

5-
@import Flutter;
65
@import XCTest;
76
@import webview_flutter_wkwebview;
87

8+
#if TARGET_OS_OSX
9+
@import FlutterMacOS;
10+
#else
11+
@import Flutter;
12+
#endif
13+
914
#import <OCMock/OCMock.h>
1015

1116
@interface FWFURLTests : XCTestCase

0 commit comments

Comments
 (0)