Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
c1de6e2
Expose the allowsLinkPreview property in WKWebView for iOS
camfrandsen Sep 27, 2023
9590857
Merge remote-tracking branch 'origin/main' into linkPreview
camfrandsen Nov 1, 2023
fe5ee5a
Resolve merge conflicts with origin/main
camfrandsen Nov 1, 2023
0d6a675
override dependencies
camfrandsen Nov 1, 2023
9889288
Merge remote-tracking branch 'origin/main' into linkPreview
camfrandsen Nov 8, 2023
31f034e
Revert changing the legacy files as they are no longer supported
camfrandsen Nov 8, 2023
ffc780f
Fix versions in Changelog and pubspec.yml. I had incorrectly fixed th…
camfrandsen Nov 9, 2023
90c93fc
Missed on legacy file that needed to be reverted
camfrandsen Nov 9, 2023
938f8e5
Fix generated files by running: flutter pub upgrade (fixes Error: Me…
camfrandsen Nov 9, 2023
0ed787d
Fix last merge conflict in FWFWebViewHostApi.m
camfrandsen Nov 9, 2023
d7ab020
update webview_flutter
bparrishMines Mar 31, 2025
3730994
update platform interface
bparrishMines Mar 31, 2025
23dde3b
remove old files
bparrishMines Mar 31, 2025
ef29572
try
bparrishMines Mar 31, 2025
045a1ee
remove change
bparrishMines Mar 31, 2025
15af7c4
add impl
bparrishMines Mar 31, 2025
45c6905
Merge branch 'main' of github.com:flutter/packages into linkPreview
bparrishMines Mar 31, 2025
1a577af
remove override and update changelog
bparrishMines Mar 31, 2025
62594dd
Revert unrelated Runner.xcodeproj change
stuartmorgan-g Apr 1, 2025
76c53c5
update location and docs
bparrishMines Apr 2, 2025
44b8475
Merge branch 'main' of github.com:flutter/packages into linkPreview
bparrishMines Apr 2, 2025
a9903d9
Merge branch 'linkPreview' of github.com:camfrandsen/packages into li…
bparrishMines Apr 2, 2025
7a46f04
update docs
bparrishMines Apr 17, 2025
34a41d9
Merge branch 'main' of github.com:flutter/packages into linkPreview
bparrishMines Apr 17, 2025
532ce62
organize methods to put platform specific near top
bparrishMines Apr 17, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/webview_flutter/webview_flutter/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 4.2.5

* Adds support for the `allowsLinkPreview` property on iOS.

## 4.2.4

* Adds pub topics to package metadata.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ class WebView extends StatefulWidget {
this.onWebResourceError,
this.debuggingEnabled = false,
this.gestureNavigationEnabled = false,
this.allowsLinkPreview = true,
this.userAgent,
this.zoomEnabled = true,
this.initialMediaPlaybackPolicy =
Expand Down Expand Up @@ -260,6 +261,13 @@ class WebView extends StatefulWidget {
/// By default `gestureNavigationEnabled` is false.
final bool gestureNavigationEnabled;

/// Whether pressing a link displays a preview of the destination for the link.
///
/// Not supported on all platforms.
///
/// By default `allowsLinkPreview` is true.
final bool allowsLinkPreview;

/// The value used for the HTTP User-Agent: request header.
///
/// When null the platform's webview default is used for the User-Agent header.
Expand Down Expand Up @@ -380,6 +388,7 @@ WebSettings _webSettingsFromWidget(WebView widget) {
hasProgressTracking: widget.onProgress != null,
debuggingEnabled: widget.debuggingEnabled,
gestureNavigationEnabled: widget.gestureNavigationEnabled,
allowsLinkPreview: widget.allowsLinkPreview,
allowsInlineMediaPlayback: widget.allowsInlineMediaPlayback,
userAgent: WebSetting<String?>.of(widget.userAgent),
zoomEnabled: widget.zoomEnabled,
Expand All @@ -397,13 +406,15 @@ WebSettings _clearUnchangedWebSettings(
assert(newValue.hasNavigationDelegate != null);
assert(newValue.debuggingEnabled != null);
assert(newValue.zoomEnabled != null);
assert(newValue.allowsLinkPreview != null);

JavascriptMode? javascriptMode;
bool? hasNavigationDelegate;
bool? hasProgressTracking;
bool? debuggingEnabled;
WebSetting<String?> userAgent = const WebSetting<String?>.absent();
bool? zoomEnabled;
bool? allowsLinkPreview;
if (currentValue.javascriptMode != newValue.javascriptMode) {
javascriptMode = newValue.javascriptMode;
}
Expand All @@ -422,6 +433,9 @@ WebSettings _clearUnchangedWebSettings(
if (currentValue.zoomEnabled != newValue.zoomEnabled) {
zoomEnabled = newValue.zoomEnabled;
}
if (currentValue.allowsLinkPreview != newValue.allowsLinkPreview) {
allowsLinkPreview = newValue.allowsLinkPreview;
}

return WebSettings(
javascriptMode: javascriptMode,
Expand All @@ -430,6 +444,7 @@ WebSettings _clearUnchangedWebSettings(
debuggingEnabled: debuggingEnabled,
userAgent: userAgent,
zoomEnabled: zoomEnabled,
allowsLinkPreview: allowsLinkPreview,
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,11 @@ class WebViewController {
Future<void> setUserAgent(String? userAgent) {
return platform.setUserAgent(userAgent);
}

/// Whether to display a preview of the destination for the link
Future<void> setAllowsLinkPreview(bool allow) {
return platform.setAllowsLinkPreview(allow);
}
}

/// Permissions request when web content requests access to protected resources.
Expand Down
2 changes: 1 addition & 1 deletion packages/webview_flutter/webview_flutter/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: webview_flutter
description: A Flutter plugin that provides a WebView widget on Android and iOS.
repository: https://github.com/flutter/packages/tree/main/packages/webview_flutter/webview_flutter
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+webview%22
version: 4.2.4
version: 4.2.5

environment:
sdk: ">=2.19.0 <4.0.0"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1114,6 +1114,58 @@ void main() {
});
});

group('allowsLinkPreview', () {
testWidgets('defaults to true', (WidgetTester tester) async {
await tester.pumpWidget(const WebView());

final CreationParams params = captureBuildArgs(
mockWebViewPlatform,
creationParams: true,
).single as CreationParams;

expect(params.webSettings!.allowsLinkPreview, true);
});

testWidgets('can be disabled', (WidgetTester tester) async {
await tester.pumpWidget(const WebView(
allowsLinkPreview: false,
));

final CreationParams params = captureBuildArgs(
mockWebViewPlatform,
creationParams: true,
).single as CreationParams;

expect(params.webSettings!.allowsLinkPreview, false);
});

testWidgets('can be changed', (WidgetTester tester) async {
final GlobalKey key = GlobalKey();
await tester.pumpWidget(WebView(key: key));

await tester.pumpWidget(WebView(
key: key,
allowsLinkPreview: false,
));

final WebSettings enabledSettings =
verify(mockWebViewPlatformController.updateSettings(captureAny))
.captured
.last as WebSettings;
expect(enabledSettings.allowsLinkPreview, false);

await tester.pumpWidget(WebView(
key: key,
));

final WebSettings disabledSettings =
verify(mockWebViewPlatformController.updateSettings(captureAny))
.captured
.last as WebSettings;
expect(disabledSettings.allowsLinkPreview, true);
});
});

group('Custom platform implementation', () {
setUp(() {
WebView.platform = MyWebViewPlatform();
Expand Down Expand Up @@ -1143,6 +1195,7 @@ void main() {
debuggingEnabled: false,
userAgent: const WebSetting<String?>.of(null),
gestureNavigationEnabled: true,
allowsLinkPreview: true,
zoomEnabled: true,
),
)));
Expand Down Expand Up @@ -1326,6 +1379,7 @@ class MatchesWebSettings extends Matcher {
_webSettings!.gestureNavigationEnabled ==
webSettings.gestureNavigationEnabled &&
_webSettings!.userAgent == webSettings.userAgent &&
_webSettings!.allowsLinkPreview == webSettings.allowsLinkPreview &&
_webSettings!.zoomEnabled == webSettings.zoomEnabled;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,18 @@ void main() {
);
});

test('setAllowsLinkPreview', () async {
final MockPlatformWebViewController mockPlatformWebViewController =
MockPlatformWebViewController();

final WebViewController webViewController = WebViewController.fromPlatform(
mockPlatformWebViewController,
);

await webViewController.setAllowsLinkPreview(false);
verify(mockPlatformWebViewController.setAllowsLinkPreview(false));
});

test('setUserAgent', () async {
final MockPlatformWebViewController mockPlatformWebViewController =
MockPlatformWebViewController();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,17 @@ class MockPlatformWebViewController extends _i1.Mock
returnValue: _i5.Future<void>.value(),
returnValueForMissingStub: _i5.Future<void>.value(),
) as _i5.Future<void>);

@override
_i5.Future<void> setAllowsLinkPreview(bool? allow) => (super.noSuchMethod(
Invocation.method(
#setAllowsLinkPreview,
[allow],
),
returnValue: _i5.Future<void>.value(),
returnValueForMissingStub: _i5.Future<void>.value(),
) as _i5.Future<void>);

@override
_i5.Future<void> setOnPlatformPermissionRequest(
void Function(_i2.PlatformWebViewPermissionRequest)?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,17 @@ class MockPlatformWebViewController extends _i1.Mock
returnValue: _i7.Future<void>.value(),
returnValueForMissingStub: _i7.Future<void>.value(),
) as _i7.Future<void>);

@override
_i7.Future<void> setAllowsLinkPreview(bool? allow) => (super.noSuchMethod(
Invocation.method(
#setAllowsLinkPreview,
[allow],
),
returnValue: _i7.Future<void>.value(),
returnValueForMissingStub: _i7.Future<void>.value(),
) as _i7.Future<void>);

@override
_i7.Future<void> setOnPlatformPermissionRequest(
void Function(_i2.PlatformWebViewPermissionRequest)?
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 2.6.1

* Adds support for the `allowsLinkPreview` property on iOS.

## 2.6.0

* Adds support to register a callback to intercept messages that are written to
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ class WebSettings {
this.hasProgressTracking,
this.debuggingEnabled,
this.gestureNavigationEnabled,
this.allowsLinkPreview,
this.allowsInlineMediaPlayback,
this.zoomEnabled,
required this.userAgent,
Expand Down Expand Up @@ -125,8 +126,13 @@ class WebSettings {
/// See also: [WebView.gestureNavigationEnabled]
final bool? gestureNavigationEnabled;

/// Determines whether pressing a link displays a preview of the destination for the link in iOS.
///
/// See also: [WebView.allowsLinkPreview]
final bool? allowsLinkPreview;

@override
String toString() {
return 'WebSettings(javascriptMode: $javascriptMode, hasNavigationDelegate: $hasNavigationDelegate, hasProgressTracking: $hasProgressTracking, debuggingEnabled: $debuggingEnabled, gestureNavigationEnabled: $gestureNavigationEnabled, userAgent: $userAgent, allowsInlineMediaPlayback: $allowsInlineMediaPlayback)';
return 'WebSettings(javascriptMode: $javascriptMode, hasNavigationDelegate: $hasNavigationDelegate, hasProgressTracking: $hasProgressTracking, debuggingEnabled: $debuggingEnabled, gestureNavigationEnabled: $gestureNavigationEnabled, allowsLinkPreview: $allowsLinkPreview, userAgent: $userAgent, allowsInlineMediaPlayback: $allowsInlineMediaPlayback)';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,11 @@ abstract class PlatformWebViewController extends PlatformInterface {
'setUserAgent is not implemented on the current platform');
}

/// Whether to display a preview of the destination for the link
///
/// This is not supported by all platforms, so it defaults to a noop
Future<void> setAllowsLinkPreview(bool allow) async {}
Copy link
Contributor Author

@camfrandsen camfrandsen Sep 28, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought it was better to default this to a noop so it wouldn't break other platforms if it was called. Having said that, I will change it to whatever you would like


/// Sets a callback that notifies the host application that web content is
/// requesting permission to access the specified resources.
Future<void> setOnPlatformPermissionRequest(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ repository: https://github.com/flutter/packages/tree/main/packages/webview_flutt
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+webview_flutter%22
# NOTE: We strongly prefer non-breaking changes, even at the expense of a
# less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes
version: 2.6.0
version: 2.6.1

environment:
sdk: ">=2.19.0 <4.0.0"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 3.8.1

* Adds support for the `allowsLinkPreview` property on iOS.

## 3.8.0

* Adds support to register a callback to receive JavaScript console messages. See `WebKitWebViewController.setOnConsoleMessage`.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,22 @@ - (void)testSetAllowsBackForwardNavigationGestures {
XCTAssertNil(error);
}

- (void)testSetAllowsLinkPreview {
FWFWebView *mockWebView = OCMClassMock([FWFWebView class]);

FWFInstanceManager *instanceManager = [[FWFInstanceManager alloc] init];
[instanceManager addDartCreatedInstance:mockWebView withIdentifier:0];

FWFWebViewHostApiImpl *hostAPI = [[FWFWebViewHostApiImpl alloc]
initWithBinaryMessenger:OCMProtocolMock(@protocol(FlutterBinaryMessenger))
instanceManager:instanceManager];

FlutterError *error;
[hostAPI setAllowsLinkPreviewForWebViewWithIdentifier:@0 isAllowed:@NO error:&error];
OCMVerify([mockWebView setAllowsLinkPreview:NO]);
XCTAssertNil(error);
}

- (void)testEvaluateJavaScript {
FWFWebView *mockWebView = OCMClassMock([FWFWebView class]);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ class WebView extends StatefulWidget {
this.onWebResourceError,
this.debuggingEnabled = false,
this.gestureNavigationEnabled = false,
this.allowsLinkPreview = true,
this.userAgent,
this.zoomEnabled = true,
this.initialMediaPlaybackPolicy =
Expand Down Expand Up @@ -205,6 +206,13 @@ class WebView extends StatefulWidget {
/// By default `gestureNavigationEnabled` is false.
final bool gestureNavigationEnabled;

/// Whether pressing a link displays a preview of the destination for the link.
///
/// Not supported on all platforms.
///
/// By default `allowsLinkPreview` is true, to match the default on iOS.
final bool allowsLinkPreview;

/// The value used for the HTTP User-Agent: request header.
///
/// When null the platform's webview default is used for the User-Agent header.
Expand Down Expand Up @@ -618,6 +626,7 @@ WebSettings _webSettingsFromWidget(WebView widget) {
hasProgressTracking: widget.onProgress != null,
debuggingEnabled: widget.debuggingEnabled,
gestureNavigationEnabled: widget.gestureNavigationEnabled,
allowsLinkPreview: widget.allowsLinkPreview,
allowsInlineMediaPlayback: widget.allowsInlineMediaPlayback,
userAgent: WebSetting<String?>.of(widget.userAgent),
zoomEnabled: widget.zoomEnabled,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -744,6 +744,9 @@ NSObject<FlutterMessageCodec> *FWFWKWebViewHostApiGetCodec(void);
- (void)setAllowsBackForwardForWebViewWithIdentifier:(NSNumber *)identifier
isAllowed:(NSNumber *)allow
error:(FlutterError *_Nullable *_Nonnull)error;
- (void)setAllowsLinkPreviewForWebViewWithIdentifier:(NSNumber *)identifier
isAllowed:(NSNumber *)allow
error:(FlutterError *_Nullable *_Nonnull)error;
- (void)setUserAgentForWebViewWithIdentifier:(NSNumber *)identifier
userAgent:(nullable NSString *)userAgent
error:(FlutterError *_Nullable *_Nonnull)error;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2459,6 +2459,32 @@ void FWFWKWebViewHostApiSetup(id<FlutterBinaryMessenger> binaryMessenger,
[channel setMessageHandler:nil];
}
}
{
FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc]
initWithName:
@"dev.flutter.pigeon.webview_flutter_wkwebview.WKWebViewHostApi.setAllowsLinkPreview"
binaryMessenger:binaryMessenger
codec:FWFWKWebViewHostApiGetCodec()];
if (api) {
NSCAssert([api respondsToSelector:@selector
(setAllowsLinkPreviewForWebViewWithIdentifier:isAllowed:error:)],
@"FWFWKWebViewHostApi api (%@) doesn't respond to "
@"@selector(setAllowsLinkPreviewForWebViewWithIdentifier:isAllowed:error:)",
api);
[channel setMessageHandler:^(id _Nullable message, FlutterReply callback) {
NSArray *args = message;
NSNumber *arg_identifier = GetNullableObjectAtIndex(args, 0);
NSNumber *arg_allow = GetNullableObjectAtIndex(args, 1);
FlutterError *error;
[api setAllowsLinkPreviewForWebViewWithIdentifier:arg_identifier
isAllowed:arg_allow
error:&error];
callback(wrapResult(nil, error));
}];
} else {
[channel setMessageHandler:nil];
}
}
{
FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc]
initWithName:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,14 @@ - (void)reloadWebViewWithIdentifier:(nonnull NSNumber *)identifier
[[self webViewForIdentifier:identifier] setAllowsBackForwardNavigationGestures:allow.boolValue];
}

- (void)
setAllowsLinkPreviewForWebViewWithIdentifier:(nonnull NSNumber *)identifier
isAllowed:(nonnull NSNumber *)allow
error:(FlutterError *_Nullable __autoreleasing *_Nonnull)
error {
[[self webViewForIdentifier:identifier] setAllowsLinkPreview:allow.boolValue];
}

- (void)
setNavigationDelegateForWebViewWithIdentifier:(nonnull NSNumber *)identifier
delegateIdentifier:(nullable NSNumber *)navigationDelegateIdentifier
Expand Down
Loading