Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.

Commit be71485

Browse files
jeremie-movifyened
authored andcommitted
[webview_flutter] Add support for onPageStarted event (#2295)
* Added support for webView's 'onPageStarted' event
1 parent e18356f commit be71485

File tree

9 files changed

+166
-0
lines changed

9 files changed

+166
-0
lines changed

packages/webview_flutter/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 0.3.18
2+
3+
* Add support for onPageStarted event.
4+
15
## 0.3.17
26

37
* Fix pedantic lint errors. Added missing documentation and awaited some futures

packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebViewClient.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
package io.flutter.plugins.webviewflutter;
66

77
import android.annotation.TargetApi;
8+
import android.graphics.Bitmap;
89
import android.os.Build;
910
import android.util.Log;
1011
import android.view.KeyEvent;
@@ -66,6 +67,12 @@ private boolean shouldOverrideUrlLoading(WebView view, String url) {
6667
return true;
6768
}
6869

70+
private void onPageStarted(WebView view, String url) {
71+
Map<String, Object> args = new HashMap<>();
72+
args.put("url", url);
73+
methodChannel.invokeMethod("onPageStarted", args);
74+
}
75+
6976
private void onPageFinished(WebView view, String url) {
7077
Map<String, Object> args = new HashMap<>();
7178
args.put("url", url);
@@ -106,6 +113,11 @@ public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request
106113
return FlutterWebViewClient.this.shouldOverrideUrlLoading(view, request);
107114
}
108115

116+
@Override
117+
public void onPageStarted(WebView view, String url, Bitmap favicon) {
118+
FlutterWebViewClient.this.onPageStarted(view, url);
119+
}
120+
109121
@Override
110122
public void onPageFinished(WebView view, String url) {
111123
FlutterWebViewClient.this.onPageFinished(view, url);
@@ -132,6 +144,11 @@ public boolean shouldOverrideUrlLoading(WebView view, String url) {
132144
return FlutterWebViewClient.this.shouldOverrideUrlLoading(view, url);
133145
}
134146

147+
@Override
148+
public void onPageStarted(WebView view, String url, Bitmap favicon) {
149+
FlutterWebViewClient.this.onPageStarted(view, url);
150+
}
151+
135152
@Override
136153
public void onPageFinished(WebView view, String url) {
137154
FlutterWebViewClient.this.onPageFinished(view, url);

packages/webview_flutter/example/lib/main.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,9 @@ class _WebViewExampleState extends State<WebViewExample> {
6868
print('allowing navigation to $request');
6969
return NavigationDecision.navigate;
7070
},
71+
onPageStarted: (String url) {
72+
print('Page started loading: $url');
73+
},
7174
onPageFinished: (String url) {
7275
print('Page finished loading: $url');
7376
},

packages/webview_flutter/example/test_driver/webview_flutter_e2e.dart

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ void main() {
6262
testWidgets('loadUrl with headers', (WidgetTester tester) async {
6363
final Completer<WebViewController> controllerCompleter =
6464
Completer<WebViewController>();
65+
final StreamController<String> pageStarts = StreamController<String>();
6566
final StreamController<String> pageLoads = StreamController<String>();
6667
await tester.pumpWidget(
6768
Directionality(
@@ -73,6 +74,9 @@ void main() {
7374
controllerCompleter.complete(controller);
7475
},
7576
javascriptMode: JavascriptMode.unrestricted,
77+
onPageStarted: (String url) {
78+
pageStarts.add(url);
79+
},
7680
onPageFinished: (String url) {
7781
pageLoads.add(url);
7882
},
@@ -88,7 +92,9 @@ void main() {
8892
final String currentUrl = await controller.currentUrl();
8993
expect(currentUrl, 'https://flutter-header-echo.herokuapp.com/');
9094

95+
await pageStarts.stream.firstWhere((String url) => url == currentUrl);
9196
await pageLoads.stream.firstWhere((String url) => url == currentUrl);
97+
9298
final String content = await controller
9399
.evaluateJavascript('document.documentElement.innerText');
94100
expect(content.contains('flutter_test_header'), isTrue);
@@ -97,6 +103,7 @@ void main() {
97103
testWidgets('JavaScriptChannel', (WidgetTester tester) async {
98104
final Completer<WebViewController> controllerCompleter =
99105
Completer<WebViewController>();
106+
final Completer<void> pageStarted = Completer<void>();
100107
final Completer<void> pageLoaded = Completer<void>();
101108
final List<String> messagesReceived = <String>[];
102109
await tester.pumpWidget(
@@ -121,13 +128,17 @@ void main() {
121128
},
122129
),
123130
].toSet(),
131+
onPageStarted: (String url) {
132+
pageStarted.complete(null);
133+
},
124134
onPageFinished: (String url) {
125135
pageLoaded.complete(null);
126136
},
127137
),
128138
),
129139
);
130140
final WebViewController controller = await controllerCompleter.future;
141+
await pageStarted.future;
131142
await pageLoaded.future;
132143

133144
expect(messagesReceived, isEmpty);
@@ -155,6 +166,7 @@ void main() {
155166
final String resizeTestBase64 =
156167
base64Encode(const Utf8Encoder().convert(resizeTest));
157168
final Completer<void> resizeCompleter = Completer<void>();
169+
final Completer<void> pageStarted = Completer<void>();
158170
final Completer<void> pageLoaded = Completer<void>();
159171
final Completer<WebViewController> controllerCompleter =
160172
Completer<WebViewController>();
@@ -176,6 +188,9 @@ void main() {
176188
},
177189
),
178190
].toSet(),
191+
onPageStarted: (String url) {
192+
pageStarted.complete(null);
193+
},
179194
onPageFinished: (String url) {
180195
pageLoaded.complete(null);
181196
},
@@ -198,6 +213,7 @@ void main() {
198213
);
199214

200215
await controllerCompleter.future;
216+
await pageStarted.future;
201217
await pageLoaded.future;
202218

203219
expect(resizeCompleter.isCompleted, false);
@@ -343,6 +359,7 @@ void main() {
343359
testWidgets('Auto media playback', (WidgetTester tester) async {
344360
Completer<WebViewController> controllerCompleter =
345361
Completer<WebViewController>();
362+
Completer<void> pageStarted = Completer<void>();
346363
Completer<void> pageLoaded = Completer<void>();
347364

348365
await tester.pumpWidget(
@@ -355,6 +372,9 @@ void main() {
355372
controllerCompleter.complete(controller);
356373
},
357374
javascriptMode: JavascriptMode.unrestricted,
375+
onPageStarted: (String url) {
376+
pageStarted.complete(null);
377+
},
358378
onPageFinished: (String url) {
359379
pageLoaded.complete(null);
360380
},
@@ -363,12 +383,14 @@ void main() {
363383
),
364384
);
365385
WebViewController controller = await controllerCompleter.future;
386+
await pageStarted.future;
366387
await pageLoaded.future;
367388

368389
String isPaused = await controller.evaluateJavascript('isPaused();');
369390
expect(isPaused, _webviewBool(false));
370391

371392
controllerCompleter = Completer<WebViewController>();
393+
pageStarted = Completer<void>();
372394
pageLoaded = Completer<void>();
373395

374396
// We change the key to re-create a new webview as we change the initialMediaPlaybackPolicy
@@ -382,6 +404,9 @@ void main() {
382404
controllerCompleter.complete(controller);
383405
},
384406
javascriptMode: JavascriptMode.unrestricted,
407+
onPageStarted: (String url) {
408+
pageStarted.complete(null);
409+
},
385410
onPageFinished: (String url) {
386411
pageLoaded.complete(null);
387412
},
@@ -392,6 +417,7 @@ void main() {
392417
);
393418

394419
controller = await controllerCompleter.future;
420+
await pageStarted.future;
395421
await pageLoaded.future;
396422

397423
isPaused = await controller.evaluateJavascript('isPaused();');
@@ -402,6 +428,7 @@ void main() {
402428
(WidgetTester tester) async {
403429
final Completer<WebViewController> controllerCompleter =
404430
Completer<WebViewController>();
431+
Completer<void> pageStarted = Completer<void>();
405432
Completer<void> pageLoaded = Completer<void>();
406433

407434
final GlobalKey key = GlobalKey();
@@ -415,6 +442,9 @@ void main() {
415442
controllerCompleter.complete(controller);
416443
},
417444
javascriptMode: JavascriptMode.unrestricted,
445+
onPageStarted: (String url) {
446+
pageStarted.complete(null);
447+
},
418448
onPageFinished: (String url) {
419449
pageLoaded.complete(null);
420450
},
@@ -423,11 +453,13 @@ void main() {
423453
),
424454
);
425455
final WebViewController controller = await controllerCompleter.future;
456+
await pageStarted.future;
426457
await pageLoaded.future;
427458

428459
String isPaused = await controller.evaluateJavascript('isPaused();');
429460
expect(isPaused, _webviewBool(false));
430461

462+
pageStarted = Completer<void>();
431463
pageLoaded = Completer<void>();
432464

433465
await tester.pumpWidget(
@@ -440,6 +472,9 @@ void main() {
440472
controllerCompleter.complete(controller);
441473
},
442474
javascriptMode: JavascriptMode.unrestricted,
475+
onPageStarted: (String url) {
476+
pageStarted.complete(null);
477+
},
443478
onPageFinished: (String url) {
444479
pageLoaded.complete(null);
445480
},
@@ -451,6 +486,7 @@ void main() {
451486

452487
await controller.reload();
453488

489+
await pageStarted.future;
454490
await pageLoaded.future;
455491

456492
isPaused = await controller.evaluateJavascript('isPaused();');
@@ -469,6 +505,7 @@ void main() {
469505
''';
470506
final String getTitleTestBase64 =
471507
base64Encode(const Utf8Encoder().convert(getTitleTest));
508+
final Completer<void> pageStarted = Completer<void>();
472509
final Completer<void> pageLoaded = Completer<void>();
473510
final Completer<WebViewController> controllerCompleter =
474511
Completer<WebViewController>();
@@ -481,6 +518,9 @@ void main() {
481518
onWebViewCreated: (WebViewController controller) {
482519
controllerCompleter.complete(controller);
483520
},
521+
onPageStarted: (String url) {
522+
pageStarted.complete(null);
523+
},
484524
onPageFinished: (String url) {
485525
pageLoaded.complete(null);
486526
},
@@ -489,6 +529,7 @@ void main() {
489529
);
490530

491531
final WebViewController controller = await controllerCompleter.future;
532+
await pageStarted.future;
492533
await pageLoaded.future;
493534

494535
final String title = await controller.getTitle();

packages/webview_flutter/ios/Classes/FLTWKNavigationDelegate.m

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,12 @@ - (instancetype)initWithChannel:(FlutterMethodChannel*)channel {
1616
return self;
1717
}
1818

19+
#pragma mark - WKNavigationDelegate conformance
20+
21+
- (void)webView:(WKWebView*)webView didStartProvisionalNavigation:(WKNavigation*)navigation {
22+
[_methodChannel invokeMethod:@"onPageStarted" arguments:@{@"url" : webView.URL.absoluteString}];
23+
}
24+
1925
- (void)webView:(WKWebView*)webView
2026
decidePolicyForNavigationAction:(WKNavigationAction*)navigationAction
2127
decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {

packages/webview_flutter/lib/platform_interface.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ abstract class WebViewPlatformCallbacksHandler {
2323
/// If true is returned the navigation is allowed, otherwise it is blocked.
2424
FutureOr<bool> onNavigationRequest({String url, bool isForMainFrame});
2525

26+
/// Invoked by [WebViewPlatformController] when a page has started loading.
27+
void onPageStarted(String url);
28+
2629
/// Invoked by [WebViewPlatformController] when a page has finished loading.
2730
void onPageFinished(String url);
2831
}

packages/webview_flutter/lib/src/webview_method_channel.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ class MethodChannelWebViewPlatform implements WebViewPlatformController {
4040
case 'onPageFinished':
4141
_platformCallbacksHandler.onPageFinished(call.arguments['url']);
4242
return null;
43+
case 'onPageStarted':
44+
_platformCallbacksHandler.onPageStarted(call.arguments['url']);
45+
return null;
4346
}
4447
throw MissingPluginException(
4548
'${call.method} was invoked but has no handler');

packages/webview_flutter/lib/webview_flutter.dart

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,9 @@ enum NavigationDecision {
7373
typedef FutureOr<NavigationDecision> NavigationDelegate(
7474
NavigationRequest navigation);
7575

76+
/// Signature for when a [WebView] has started loading a page.
77+
typedef void PageStartedCallback(String url);
78+
7679
/// Signature for when a [WebView] has finished loading a page.
7780
typedef void PageFinishedCallback(String url);
7881

@@ -142,6 +145,7 @@ class WebView extends StatefulWidget {
142145
this.javascriptChannels,
143146
this.navigationDelegate,
144147
this.gestureRecognizers,
148+
this.onPageStarted,
145149
this.onPageFinished,
146150
this.debuggingEnabled = false,
147151
this.userAgent,
@@ -257,6 +261,9 @@ class WebView extends StatefulWidget {
257261
/// * When a navigationDelegate is set HTTP requests do not include the HTTP referer header.
258262
final NavigationDelegate navigationDelegate;
259263

264+
/// Invoked when a page starts loading.
265+
final PageStartedCallback onPageStarted;
266+
260267
/// Invoked when a page has finished loading.
261268
///
262269
/// This is invoked only for the main frame.
@@ -452,6 +459,13 @@ class _PlatformCallbacksHandler implements WebViewPlatformCallbacksHandler {
452459
return allowNavigation;
453460
}
454461

462+
@override
463+
void onPageStarted(String url) {
464+
if (_widget.onPageStarted != null) {
465+
_widget.onPageStarted(url);
466+
}
467+
}
468+
455469
@override
456470
void onPageFinished(String url) {
457471
if (_widget.onPageFinished != null) {

0 commit comments

Comments
 (0)