Skip to content

Commit

Permalink
[webview] Add macOS support in implementation package (flutter#6221)
Browse files Browse the repository at this point in the history
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#41725
  • Loading branch information
stuartmorgan authored Aug 20, 2024
1 parent 584eee3 commit 4d2d2e3
Show file tree
Hide file tree
Showing 130 changed files with 5,765 additions and 2,352 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
## NEXT
## 3.15.0

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

## 3.14.0

Expand Down Expand Up @@ -92,7 +92,7 @@

* Introduces `NSError.toString` for better diagnostics.

## 3.6.2
## 3.6.2

* Fixes unawaited_futures violations.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,15 @@
// 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;

#if TARGET_OS_OSX
@import FlutterMacOS;
#else
@import Flutter;
#endif

#import <OCMock/OCMock.h>

@interface FWFDataConvertersTests : XCTestCase
Expand Down Expand Up @@ -61,8 +66,8 @@ - (void)testFWFWKNavigationActionDataFromNavigationAction {

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

NSURLRequest *request =
[NSURLRequest requestWithURL:[NSURL URLWithString:@"https://www.flutter.dev/"]];
NSURL *testURL = [NSURL URLWithString:@"https://www.flutter.dev/"];
NSURLRequest *request = [NSURLRequest requestWithURL:testURL];
OCMStub([mockNavigationAction request]).andReturn(request);

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

- (void)testFWFNSUrlRequestDataFromNSURLRequest {
NSMutableURLRequest *request =
[NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"https://www.flutter.dev/"]];
NSURL *testURL = [NSURL URLWithString:@"https://www.flutter.dev/"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:testURL];
request.HTTPMethod = @"POST";
request.HTTPBody = [@"aString" dataUsingEncoding:NSUTF8StringEncoding];
request.allHTTPHeaderFields = @{@"a" : @"field"};
Expand Down Expand Up @@ -137,7 +142,7 @@ - (void)testFWFWKSecurityOriginDataFromWKSecurityOrigin {
XCTAssertEqualObjects(data.protocol, @"protocol");
}

- (void)testFWFWKPermissionDecisionFromData API_AVAILABLE(ios(15.0)) {
- (void)testFWFWKPermissionDecisionFromData API_AVAILABLE(ios(15.0), macos(12)) {
XCTAssertEqual(FWFNativeWKPermissionDecisionFromData(
[FWFWKPermissionDecisionData makeWithValue:FWFWKPermissionDecisionDeny]),
WKPermissionDecisionDeny);
Expand All @@ -149,7 +154,7 @@ - (void)testFWFWKPermissionDecisionFromData API_AVAILABLE(ios(15.0)) {
WKPermissionDecisionPrompt);
}

- (void)testFWFWKMediaCaptureTypeDataFromWKMediaCaptureType API_AVAILABLE(ios(15.0)) {
- (void)testFWFWKMediaCaptureTypeDataFromWKMediaCaptureType API_AVAILABLE(ios(15.0), macos(12)) {
XCTAssertEqual(
FWFWKMediaCaptureTypeDataFromNativeWKMediaCaptureType(WKMediaCaptureTypeCamera).value,
FWFWKMediaCaptureTypeCamera);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,15 @@
// 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;

#if TARGET_OS_OSX
@import FlutterMacOS;
#else
@import Flutter;
#endif

#import <OCMock/OCMock.h>

@interface FWFHTTPCookieStoreHostApiTests : XCTestCase
Expand Down Expand Up @@ -47,9 +52,8 @@ - (void)testSetCookie {
completion:^(FlutterError *error) {
blockError = error;
}];
OCMVerify([mockHttpCookieStore
setCookie:[NSHTTPCookie cookieWithProperties:@{NSHTTPCookieName : @"hello"}]
completionHandler:OCMOCK_ANY]);
NSHTTPCookie *cookie = [NSHTTPCookie cookieWithProperties:@{NSHTTPCookieName : @"hello"}];
OCMVerify([mockHttpCookieStore setCookie:cookie completionHandler:OCMOCK_ANY]);
XCTAssertNil(blockError);
}
@end
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#import <XCTest/XCTest.h>
@import XCTest;

@import webview_flutter_wkwebview;
#if __has_include(<webview_flutter_wkwebview/webview-umbrella.h>)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,15 @@
// 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;

#if TARGET_OS_OSX
@import FlutterMacOS;
#else
@import Flutter;
#endif

#import <OCMock/OCMock.h>

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

WKNavigationAction *mockNavigationAction = OCMClassMock([WKNavigationAction class]);
OCMStub([mockNavigationAction request])
.andReturn([NSURLRequest requestWithURL:[NSURL URLWithString:@"https://www.flutter.dev"]]);
NSURL *testURL = [NSURL URLWithString:@"https://www.flutter.dev"];
OCMStub([mockNavigationAction request]).andReturn([NSURLRequest requestWithURL:testURL]);

WKFrameInfo *mockFrameInfo = OCMClassMock([WKFrameInfo class]);
OCMStub([mockFrameInfo isMainFrame]).andReturn(YES);
Expand Down Expand Up @@ -258,10 +263,10 @@ - (void)testDidReceiveAuthenticationChallenge {
NSURLCredential *__block callbackCredential;
[mockDelegate webView:mockWebView
didReceiveAuthenticationChallenge:mockChallenge
completionHandler:^(NSURLSessionAuthChallengeDisposition disposition,
NSURLCredential *credential) {
callbackDisposition = disposition;
callbackCredential = credential;
completionHandler:^(NSURLSessionAuthChallengeDisposition dispositionArg,
NSURLCredential *credentialArg) {
callbackDisposition = dispositionArg;
callbackCredential = credentialArg;
}];

XCTAssertEqual(callbackDisposition, NSURLSessionAuthChallengeCancelAuthenticationChallenge);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,15 @@
// 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;

#if TARGET_OS_OSX
@import FlutterMacOS;
#else
@import Flutter;
#endif

#import <OCMock/OCMock.h>

@interface FWFObjectHostApiTests : XCTestCase
Expand Down Expand Up @@ -139,8 +144,10 @@ - (void)testObserveValueForKeyPath {
return value[0].value == FWFNSKeyValueChangeKeyEnumOldValue;
}]
changeValues:[OCMArg checkWithBlock:^BOOL(id value) {
FWFObjectOrIdentifier *object = (FWFObjectOrIdentifier *)value[0];
return !object.isIdentifier && [@"key" isEqual:object.value];
FWFObjectOrIdentifier *changeObject =
(FWFObjectOrIdentifier *)value[0];
return !changeObject.isIdentifier &&
[@"key" isEqual:changeObject.value];
}]
completion:OCMOCK_ANY]);
}
Expand Down Expand Up @@ -173,8 +180,10 @@ - (void)testObserveValueForKeyPathWithIdentifier {
return value[0].value == FWFNSKeyValueChangeKeyEnumOldValue;
}]
changeValues:[OCMArg checkWithBlock:^BOOL(id value) {
FWFObjectOrIdentifier *object = (FWFObjectOrIdentifier *)value[0];
return object.isIdentifier && [@(2) isEqual:object.value];
FWFObjectOrIdentifier *changeObject =
(FWFObjectOrIdentifier *)value[0];
return changeObject.isIdentifier &&
[@(2) isEqual:changeObject.value];
}]
completion:OCMOCK_ANY]);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,15 @@
// 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;

#if TARGET_OS_OSX
@import FlutterMacOS;
#else
@import Flutter;
#endif

#import <OCMock/OCMock.h>

@interface FWFPreferencesHostApiTests : XCTestCase
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,15 @@
// 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;

#if TARGET_OS_OSX
@import FlutterMacOS;
#else
@import Flutter;
#endif

#import <OCMock/OCMock.h>

@interface FWFScriptMessageHandlerHostApiTests : XCTestCase
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "TargetConditionals.h"

// The scroll view delegate does not exist on macOS.
#if !TARGET_OS_OSX

@import Flutter;
@import XCTest;
@import webview_flutter_wkwebview;
Expand Down Expand Up @@ -80,3 +85,5 @@ - (void)testOnScrollViewDidScrollForDelegateWithIdentifier {
completion:OCMOCK_ANY]);
}
@end

#endif // !TARGET_OS_OSX
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#import "TargetConditionals.h"

// Scroll view APIs do not existing on macOS.
#if !TARGET_OS_OSX

@import Flutter;
@import XCTest;
@import webview_flutter_wkwebview;
Expand Down Expand Up @@ -79,3 +84,5 @@ - (void)testSetDelegateForScrollView {
XCTAssertNil(error);
}
@end

#endif // !TARGET_OS_OSX
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,18 @@
// 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;
#if __has_include(<webview_flutter_wkwebview/webview-umbrella.h>)
@import webview_flutter_wkwebview.Test;
#endif

#if TARGET_OS_OSX
@import FlutterMacOS;
#else
@import Flutter;
#endif

#import <OCMock/OCMock.h>

@interface FWFUIDelegateHostApiTests : XCTestCase
Expand Down Expand Up @@ -77,8 +82,8 @@ - (void)testOnCreateWebViewForDelegateWithIdentifier {
.ignoringNonObjectArgs();

WKNavigationAction *mockNavigationAction = OCMClassMock([WKNavigationAction class]);
OCMStub([mockNavigationAction request])
.andReturn([NSURLRequest requestWithURL:[NSURL URLWithString:@"https://www.flutter.dev"]]);
NSURL *testURL = [NSURL URLWithString:@"https://www.flutter.dev"];
OCMStub([mockNavigationAction request]).andReturn([NSURLRequest requestWithURL:testURL]);

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

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

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

#import "TargetConditionals.h"

#if !TARGET_OS_OSX

@import Flutter;
@import XCTest;
@import webview_flutter_wkwebview;
Expand Down Expand Up @@ -47,3 +51,5 @@ - (void)testSetOpaque {
}

@end

#endif // !TARGET_OS_OSX
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,15 @@
// 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;

#if TARGET_OS_OSX
@import FlutterMacOS;
#else
@import Flutter;
#endif

#import <OCMock/OCMock.h>

@interface FWFURLAuthenticationChallengeHostApiTests : XCTestCase
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,15 @@
// 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;

#if TARGET_OS_OSX
@import FlutterMacOS;
#else
@import Flutter;
#endif

#import <OCMock/OCMock.h>

@interface FWFURLCredentialHostApiTests : XCTestCase
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,15 @@
// 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;

#if TARGET_OS_OSX
@import FlutterMacOS;
#else
@import Flutter;
#endif

#import <OCMock/OCMock.h>

@interface FWFURLProtectionSpaceHostApiTests : XCTestCase
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,15 @@
// 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;

#if TARGET_OS_OSX
@import FlutterMacOS;
#else
@import Flutter;
#endif

#import <OCMock/OCMock.h>

@interface FWFURLTests : XCTestCase
Expand Down
Loading

0 comments on commit 4d2d2e3

Please sign in to comment.