Skip to content

Commit 78eff18

Browse files
authored
[webview_flutter] Migrate to nnbd (flutter#3327)
1 parent ad6d03c commit 78eff18

9 files changed

+273
-276
lines changed

packages/webview_flutter/CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 2.0.0-nullsafety
2+
3+
* Migration to null-safety.
4+
15
## 1.0.8
26

37
* Update Flutter SDK constraint.

packages/webview_flutter/lib/platform_interface.dart

+36-28
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ abstract class WebViewPlatformCallbacksHandler {
2121
/// Invoked by [WebViewPlatformController] when a navigation request is pending.
2222
///
2323
/// If true is returned the navigation is allowed, otherwise it is blocked.
24-
FutureOr<bool> onNavigationRequest({String url, bool isForMainFrame});
24+
FutureOr<bool> onNavigationRequest(
25+
{required String url, required bool isForMainFrame});
2526

2627
/// Invoked by [WebViewPlatformController] when a page has started loading.
2728
void onPageStarted(String url);
@@ -103,8 +104,8 @@ class WebResourceError {
103104
/// A user should not need to instantiate this class, but will receive one in
104105
/// [WebResourceErrorCallback].
105106
WebResourceError({
106-
@required this.errorCode,
107-
@required this.description,
107+
required this.errorCode,
108+
required this.description,
108109
this.domain,
109110
this.errorType,
110111
this.failingUrl,
@@ -131,21 +132,21 @@ class WebResourceError {
131132
/// in Objective-C. See
132133
/// https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/ErrorHandlingCocoa/ErrorObjectsDomains/ErrorObjectsDomains.html
133134
/// for more information on error handling on iOS.
134-
final String domain;
135+
final String? domain;
135136

136137
/// Description of the error that can be used to communicate the problem to the user.
137138
final String description;
138139

139140
/// The type this error can be categorized as.
140141
///
141142
/// This will never be `null` on Android, but can be `null` on iOS.
142-
final WebResourceErrorType errorType;
143+
final WebResourceErrorType? errorType;
143144

144145
/// Gets the URL for which the resource request was made.
145146
///
146147
/// This value is not provided on iOS. Alternatively, you can keep track of
147148
/// the last values provided to [WebViewPlatformController.loadUrl].
148-
final String failingUrl;
149+
final String? failingUrl;
149150
}
150151

151152
/// Interface for talking to the webview's platform implementation.
@@ -176,7 +177,7 @@ abstract class WebViewPlatformController {
176177
/// Throws an ArgumentError if `url` is not a valid URL string.
177178
Future<void> loadUrl(
178179
String url,
179-
Map<String, String> headers,
180+
Map<String, String>? headers,
180181
) {
181182
throw UnimplementedError(
182183
"WebView loadUrl is not implemented on the current platform");
@@ -194,7 +195,7 @@ abstract class WebViewPlatformController {
194195
/// Accessor to the current URL that the WebView is displaying.
195196
///
196197
/// If no URL was ever loaded, returns `null`.
197-
Future<String> currentUrl() {
198+
Future<String?> currentUrl() {
198199
throw UnimplementedError(
199200
"WebView currentUrl is not implemented on the current platform");
200201
}
@@ -281,7 +282,7 @@ abstract class WebViewPlatformController {
281282
}
282283

283284
/// Returns the title of the currently loaded page.
284-
Future<String> getTitle() {
285+
Future<String?> getTitle() {
285286
throw UnimplementedError(
286287
"WebView getTitle is not implemented on the current platform");
287288
}
@@ -337,7 +338,7 @@ class WebSetting<T> {
337338
: _value = value,
338339
isPresent = true;
339340

340-
final T _value;
341+
final T? _value;
341342

342343
/// The setting's value.
343344
///
@@ -347,7 +348,14 @@ class WebSetting<T> {
347348
throw StateError('Cannot access a value of an absent WebSetting');
348349
}
349350
assert(isPresent);
350-
return _value;
351+
// The intention of this getter is to return T whether it is nullable or
352+
// not whereas _value is of type T? since _value can be null even when
353+
// T is not nullable (when isPresent == false).
354+
//
355+
// We promote _value to T using `as T` instead of `!` operator to handle
356+
// the case when _value is legitimately null (and T is a nullable type).
357+
// `!` operator would always throw if _value is null.
358+
return _value as T;
351359
}
352360

353361
/// True when this web setting instance contains a value.
@@ -358,7 +366,7 @@ class WebSetting<T> {
358366
@override
359367
bool operator ==(Object other) {
360368
if (other.runtimeType != runtimeType) return false;
361-
final WebSetting<T> typedOther = other;
369+
final WebSetting<T> typedOther = other as WebSetting<T>;
362370
return typedOther.isPresent == isPresent && typedOther._value == _value;
363371
}
364372

@@ -382,19 +390,19 @@ class WebSettings {
382390
this.hasNavigationDelegate,
383391
this.debuggingEnabled,
384392
this.gestureNavigationEnabled,
385-
@required this.userAgent,
393+
required this.userAgent,
386394
}) : assert(userAgent != null);
387395

388396
/// The JavaScript execution mode to be used by the webview.
389-
final JavascriptMode javascriptMode;
397+
final JavascriptMode? javascriptMode;
390398

391399
/// Whether the [WebView] has a [NavigationDelegate] set.
392-
final bool hasNavigationDelegate;
400+
final bool? hasNavigationDelegate;
393401

394402
/// Whether to enable the platform's webview content debugging tools.
395403
///
396404
/// See also: [WebView.debuggingEnabled].
397-
final bool debuggingEnabled;
405+
final bool? debuggingEnabled;
398406

399407
/// The value used for the HTTP `User-Agent:` request header.
400408
///
@@ -404,12 +412,12 @@ class WebSettings {
404412
/// last time it was set.
405413
///
406414
/// See also [WebView.userAgent].
407-
final WebSetting<String> userAgent;
415+
final WebSetting<String?> userAgent;
408416

409417
/// Whether to allow swipe based navigation in iOS.
410418
///
411419
/// See also: [WebView.gestureNavigationEnabled]
412-
final bool gestureNavigationEnabled;
420+
final bool? gestureNavigationEnabled;
413421

414422
@override
415423
String toString() {
@@ -428,7 +436,7 @@ class CreationParams {
428436
CreationParams({
429437
this.initialUrl,
430438
this.webSettings,
431-
this.javascriptChannelNames,
439+
this.javascriptChannelNames = const <String>{},
432440
this.userAgent,
433441
this.autoMediaPlaybackPolicy =
434442
AutoMediaPlaybackPolicy.require_user_action_for_all_media_types,
@@ -437,12 +445,12 @@ class CreationParams {
437445
/// The initialUrl to load in the webview.
438446
///
439447
/// When null the webview will be created without loading any page.
440-
final String initialUrl;
448+
final String? initialUrl;
441449

442450
/// The initial [WebSettings] for the new webview.
443451
///
444452
/// This can later be updated with [WebViewPlatformController.updateSettings].
445-
final WebSettings webSettings;
453+
final WebSettings? webSettings;
446454

447455
/// The initial set of JavaScript channels that are configured for this webview.
448456
///
@@ -460,7 +468,7 @@ class CreationParams {
460468
/// The value used for the HTTP User-Agent: request header.
461469
///
462470
/// When null the platform's webview default is used for the User-Agent header.
463-
final String userAgent;
471+
final String? userAgent;
464472

465473
/// Which restrictions apply on automatic media playback.
466474
final AutoMediaPlaybackPolicy autoMediaPlaybackPolicy;
@@ -475,7 +483,7 @@ class CreationParams {
475483
///
476484
/// See also the `onWebViewPlatformCreated` argument for [WebViewPlatform.build].
477485
typedef WebViewPlatformCreatedCallback = void Function(
478-
WebViewPlatformController webViewPlatformController);
486+
WebViewPlatformController? webViewPlatformController);
479487

480488
/// Interface for a platform implementation of a WebView.
481489
///
@@ -505,14 +513,14 @@ abstract class WebViewPlatform {
505513
///
506514
/// `webViewPlatformHandler` must not be null.
507515
Widget build({
508-
BuildContext context,
516+
required BuildContext context,
509517
// TODO(amirh): convert this to be the actual parameters.
510518
// I'm starting without it as the PR is starting to become pretty big.
511519
// I'll followup with the conversion PR.
512-
CreationParams creationParams,
513-
@required WebViewPlatformCallbacksHandler webViewPlatformCallbacksHandler,
514-
WebViewPlatformCreatedCallback onWebViewPlatformCreated,
515-
Set<Factory<OneSequenceGestureRecognizer>> gestureRecognizers,
520+
required CreationParams creationParams,
521+
required WebViewPlatformCallbacksHandler webViewPlatformCallbacksHandler,
522+
WebViewPlatformCreatedCallback? onWebViewPlatformCreated,
523+
Set<Factory<OneSequenceGestureRecognizer>>? gestureRecognizers,
516524
});
517525

518526
/// Clears all cookies for all [WebView] instances.

packages/webview_flutter/lib/src/webview_android.dart

+5-5
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@ import 'webview_method_channel.dart';
2020
class AndroidWebView implements WebViewPlatform {
2121
@override
2222
Widget build({
23-
BuildContext context,
24-
CreationParams creationParams,
25-
@required WebViewPlatformCallbacksHandler webViewPlatformCallbacksHandler,
26-
WebViewPlatformCreatedCallback onWebViewPlatformCreated,
27-
Set<Factory<OneSequenceGestureRecognizer>> gestureRecognizers,
23+
required BuildContext context,
24+
required CreationParams creationParams,
25+
required WebViewPlatformCallbacksHandler webViewPlatformCallbacksHandler,
26+
WebViewPlatformCreatedCallback? onWebViewPlatformCreated,
27+
Set<Factory<OneSequenceGestureRecognizer>>? gestureRecognizers,
2828
}) {
2929
assert(webViewPlatformCallbacksHandler != null);
3030
return GestureDetector(

packages/webview_flutter/lib/src/webview_cupertino.dart

+5-5
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@ import 'webview_method_channel.dart';
2020
class CupertinoWebView implements WebViewPlatform {
2121
@override
2222
Widget build({
23-
BuildContext context,
24-
CreationParams creationParams,
25-
@required WebViewPlatformCallbacksHandler webViewPlatformCallbacksHandler,
26-
WebViewPlatformCreatedCallback onWebViewPlatformCreated,
27-
Set<Factory<OneSequenceGestureRecognizer>> gestureRecognizers,
23+
required BuildContext context,
24+
required CreationParams creationParams,
25+
required WebViewPlatformCallbacksHandler webViewPlatformCallbacksHandler,
26+
WebViewPlatformCreatedCallback? onWebViewPlatformCreated,
27+
Set<Factory<OneSequenceGestureRecognizer>>? gestureRecognizers,
2828
}) {
2929
return UiKitView(
3030
viewType: 'plugins.flutter.io/webview',

packages/webview_flutter/lib/src/webview_method_channel.dart

+30-26
Original file line numberDiff line numberDiff line change
@@ -25,31 +25,31 @@ class MethodChannelWebViewPlatform implements WebViewPlatformController {
2525
static const MethodChannel _cookieManagerChannel =
2626
MethodChannel('plugins.flutter.io/cookie_manager');
2727

28-
Future<bool> _onMethodCall(MethodCall call) async {
28+
Future<bool?> _onMethodCall(MethodCall call) async {
2929
switch (call.method) {
3030
case 'javascriptChannelMessage':
31-
final String channel = call.arguments['channel'];
32-
final String message = call.arguments['message'];
31+
final String channel = call.arguments['channel']!;
32+
final String message = call.arguments['message']!;
3333
_platformCallbacksHandler.onJavaScriptChannelMessage(channel, message);
3434
return true;
3535
case 'navigationRequest':
3636
return await _platformCallbacksHandler.onNavigationRequest(
37-
url: call.arguments['url'],
38-
isForMainFrame: call.arguments['isForMainFrame'],
37+
url: call.arguments['url']!,
38+
isForMainFrame: call.arguments['isForMainFrame']!,
3939
);
4040
case 'onPageFinished':
41-
_platformCallbacksHandler.onPageFinished(call.arguments['url']);
41+
_platformCallbacksHandler.onPageFinished(call.arguments['url']!);
4242
return null;
4343
case 'onPageStarted':
44-
_platformCallbacksHandler.onPageStarted(call.arguments['url']);
44+
_platformCallbacksHandler.onPageStarted(call.arguments['url']!);
4545
return null;
4646
case 'onWebResourceError':
4747
_platformCallbacksHandler.onWebResourceError(
4848
WebResourceError(
49-
errorCode: call.arguments['errorCode'],
50-
description: call.arguments['description'],
49+
errorCode: call.arguments['errorCode']!,
50+
description: call.arguments['description']!,
51+
failingUrl: call.arguments['failingUrl']!,
5152
domain: call.arguments['domain'],
52-
failingUrl: call.arguments['failingUrl'],
5353
errorType: call.arguments['errorType'] == null
5454
? null
5555
: WebResourceErrorType.values.firstWhere(
@@ -71,7 +71,7 @@ class MethodChannelWebViewPlatform implements WebViewPlatformController {
7171
@override
7272
Future<void> loadUrl(
7373
String url,
74-
Map<String, String> headers,
74+
Map<String, String>? headers,
7575
) async {
7676
assert(url != null);
7777
return _channel.invokeMethod<void>('loadUrl', <String, dynamic>{
@@ -81,13 +81,15 @@ class MethodChannelWebViewPlatform implements WebViewPlatformController {
8181
}
8282

8383
@override
84-
Future<String> currentUrl() => _channel.invokeMethod<String>('currentUrl');
84+
Future<String?> currentUrl() => _channel.invokeMethod<String>('currentUrl');
8585

8686
@override
87-
Future<bool> canGoBack() => _channel.invokeMethod<bool>("canGoBack");
87+
Future<bool> canGoBack() =>
88+
_channel.invokeMethod<bool>("canGoBack").then((result) => result!);
8889

8990
@override
90-
Future<bool> canGoForward() => _channel.invokeMethod<bool>("canGoForward");
91+
Future<bool> canGoForward() =>
92+
_channel.invokeMethod<bool>("canGoForward").then((result) => result!);
9193

9294
@override
9395
Future<void> goBack() => _channel.invokeMethod<void>("goBack");
@@ -102,18 +104,18 @@ class MethodChannelWebViewPlatform implements WebViewPlatformController {
102104
Future<void> clearCache() => _channel.invokeMethod<void>("clearCache");
103105

104106
@override
105-
Future<void> updateSettings(WebSettings settings) {
107+
Future<void> updateSettings(WebSettings settings) async {
106108
final Map<String, dynamic> updatesMap = _webSettingsToMap(settings);
107-
if (updatesMap.isEmpty) {
108-
return null;
109+
if (updatesMap.isNotEmpty) {
110+
await _channel.invokeMethod<void>('updateSettings', updatesMap);
109111
}
110-
return _channel.invokeMethod<void>('updateSettings', updatesMap);
111112
}
112113

113114
@override
114115
Future<String> evaluateJavascript(String javascriptString) {
115-
return _channel.invokeMethod<String>(
116-
'evaluateJavascript', javascriptString);
116+
return _channel
117+
.invokeMethod<String>('evaluateJavascript', javascriptString)
118+
.then((result) => result!);
117119
}
118120

119121
@override
@@ -129,7 +131,7 @@ class MethodChannelWebViewPlatform implements WebViewPlatformController {
129131
}
130132

131133
@override
132-
Future<String> getTitle() => _channel.invokeMethod<String>("getTitle");
134+
Future<String?> getTitle() => _channel.invokeMethod<String>("getTitle");
133135

134136
@override
135137
Future<void> scrollTo(int x, int y) {
@@ -148,19 +150,21 @@ class MethodChannelWebViewPlatform implements WebViewPlatformController {
148150
}
149151

150152
@override
151-
Future<int> getScrollX() => _channel.invokeMethod<int>("getScrollX");
153+
Future<int> getScrollX() =>
154+
_channel.invokeMethod<int>("getScrollX").then((result) => result!);
152155

153156
@override
154-
Future<int> getScrollY() => _channel.invokeMethod<int>("getScrollY");
157+
Future<int> getScrollY() =>
158+
_channel.invokeMethod<int>("getScrollY").then((result) => result!);
155159

156160
/// Method channel implementation for [WebViewPlatform.clearCookies].
157161
static Future<bool> clearCookies() {
158162
return _cookieManagerChannel
159163
.invokeMethod<bool>('clearCookies')
160-
.then<bool>((dynamic result) => result);
164+
.then<bool>((dynamic result) => result!);
161165
}
162166

163-
static Map<String, dynamic> _webSettingsToMap(WebSettings settings) {
167+
static Map<String, dynamic> _webSettingsToMap(WebSettings? settings) {
164168
final Map<String, dynamic> map = <String, dynamic>{};
165169
void _addIfNonNull(String key, dynamic value) {
166170
if (value == null) {
@@ -176,7 +180,7 @@ class MethodChannelWebViewPlatform implements WebViewPlatformController {
176180
map[key] = setting.value;
177181
}
178182

179-
_addIfNonNull('jsMode', settings.javascriptMode?.index);
183+
_addIfNonNull('jsMode', settings!.javascriptMode?.index);
180184
_addIfNonNull('hasNavigationDelegate', settings.hasNavigationDelegate);
181185
_addIfNonNull('debuggingEnabled', settings.debuggingEnabled);
182186
_addIfNonNull(

0 commit comments

Comments
 (0)