Skip to content

[webview_flutter] Adds app facing implementation to override console log #4705

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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.4.0

* Adds support to register a callback to receive JavaScript console messages. See `WebViewController.setConsoleLogCallback`.

## 4.3.0

* Adds support to retrieve the user agent. See `WebViewController.getUserAgent`.
Expand Down
52 changes: 52 additions & 0 deletions packages/webview_flutter/webview_flutter/example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,40 @@ const String kTransparentBackgroundPage = '''
</html>
''';

const String kLogExamplePage = '''
<!DOCTYPE html>
<html lang="en">
<head>
<title>Load file or HTML string example</title>
</head>
<body onload="console.log('Logging that the page is loading.')">

<h1>Local demo page</h1>
<p>
This page is used to test the forwarding of console logs to Dart.
</p>

<style>
.btn-group button {
padding: 24px; 24px;
display: block;
width: 25%;
margin: 5px 0px 0px 0px;
}
</style>

<div class="btn-group">
<button onclick="console.error('This is an error message.')">Error</button>
<button onclick="console.warn('This is a warning message.')">Warning</button>
<button onclick="console.info('This is a info message.')">Info</button>
<button onclick="console.debug('This is a debug message.')">Debug</button>
<button onclick="console.log('This is a log message.')">Log</button>
</div>

</body>
</html>
''';

class WebViewExample extends StatefulWidget {
const WebViewExample({super.key});

Expand Down Expand Up @@ -208,6 +242,7 @@ enum MenuOptions {
loadHtmlString,
transparentBackground,
setCookie,
logExample,
}

class SampleMenu extends StatelessWidget {
Expand Down Expand Up @@ -264,6 +299,9 @@ class SampleMenu extends StatelessWidget {
case MenuOptions.setCookie:
_onSetCookie();
break;
case MenuOptions.logExample:
_onLogExample();
break;
}
},
itemBuilder: (BuildContext context) => <PopupMenuItem<MenuOptions>>[
Expand Down Expand Up @@ -320,6 +358,10 @@ class SampleMenu extends StatelessWidget {
value: MenuOptions.setCookie,
child: Text('Set cookie'),
),
const PopupMenuItem<MenuOptions>(
value: MenuOptions.logExample,
child: Text('Log example'),
),
],
);
}
Expand Down Expand Up @@ -463,6 +505,16 @@ class SampleMenu extends StatelessWidget {

return indexFile.path;
}

Future<void> _onLogExample() {
webViewController
.setOnConsoleMessage((JavaScriptConsoleMessage consoleMessage) {
debugPrint(
'== JS == ${consoleMessage.level.name}: ${consoleMessage.message}');
});

return webViewController.loadHtmlString(kLogExamplePage);
}
}

class NavigationControls extends StatelessWidget {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,22 @@ class WebViewController {
return platform.setUserAgent(userAgent);
}

/// Sets a callback that notifies the host application on any log messages
/// written to the JavaScript console.
///
/// Platforms may not preserve all the log level information so clients should
/// not rely on a 1:1 mapping between the JavaScript calls.
///
/// On iOS setting this callback will inject a custom [WKUserScript] which
/// overrides the default implementation of `console.debug`, `console.error`,
/// `console.info`, `console.log` and `console.warning` methods. The iOS
/// WebKit framework unfortunately doesn't provide a built-in method to
/// forward console messages.
Future<void> setOnConsoleMessage(
void Function(JavaScriptConsoleMessage message) onConsoleMessage) {
return platform.setOnConsoleMessage(onConsoleMessage);
}

/// Gets the value used for the HTTP `User-Agent:` request header.
Future<String?> getUserAgent() {
return platform.getUserAgent();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ library webview_flutter;

export 'package:webview_flutter_platform_interface/webview_flutter_platform_interface.dart'
show
JavaScriptConsoleMessage,
JavaScriptMessage,
JavaScriptMode,
LoadRequestMethod,
Expand Down
6 changes: 3 additions & 3 deletions 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.3.0
version: 4.4.0

environment:
sdk: ">=2.19.0 <4.0.0"
Expand All @@ -19,9 +19,9 @@ flutter:
dependencies:
flutter:
sdk: flutter
webview_flutter_android: ^3.0.0
webview_flutter_android: ^3.12.0
webview_flutter_platform_interface: ^2.6.0
webview_flutter_wkwebview: ^3.0.0
webview_flutter_wkwebview: ^3.9.0

dev_dependencies:
build_runner: ^2.1.5
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,21 @@ void main() {
expect(permissionRequestCallbackCalled, isTrue);
});

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

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

void onConsoleMessage(JavaScriptConsoleMessage message) {}

await webViewController.setOnConsoleMessage(onConsoleMessage);

verify(mockPlatformWebViewController.setOnConsoleMessage(onConsoleMessage));
});

test('getUserAgent', () async {
final MockPlatformWebViewController mockPlatformWebViewController =
MockPlatformWebViewController();
Expand All @@ -401,7 +416,6 @@ void main() {
final WebViewController webViewController = WebViewController.fromPlatform(
mockPlatformWebViewController,
);

await expectLater(webViewController.getUserAgent(), completion(userAgent));
});
}
Expand Down