I'm building a vidsrc.to client to watch movies on my Android phone, using webview_flutter 4.x, I want to load a specific embedded video page inside a WebView, but I need to prevent the webpage from navigating the WebView to other domains or opening external pages.
My current setup is roughly:
controller = WebViewController()
..setJavaScriptMode(JavaScriptMode.unrestricted)
..loadRequest(Uri.parse('https://vidsrc.to/embed/movie/tt17048515'));
}
The page itself contains iframes and JavaScript that load resources from other domains. For example, the initial page can load content from vsembed.ru and other third-party domains.
I tried using NavigationDelegate:
..setNavigationDelegate(
NavigationDelegate(
onNavigationRequest: (request) {
final uri = Uri.tryParse(request.url);
if (uri == null) {
return NavigationDecision.prevent;
}
const allowedHosts = {'vidsrc.to','vsembed.ru',};
return allowedHosts.contains(uri.host)
? NavigationDecision.navigate
: NavigationDecision.prevent;
},
),
)
This works for top-level navigation, but it doesn't seem to prevent JavaScript/iframes inside the page from loading resources or attempting to access other domains
Minimal reproducible example:
import 'package:flutter/material.dart'; import 'package:webview_flutter/webview_flutter.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); Widget build(BuildContext context) { return const MaterialApp( home: WebViewPage(), ); } } class WebViewPage extends StatefulWidget { const WebViewPage({super.key}); State<WebViewPage> createState() => _WebViewPageState(); } class _WebViewPageState extends State<WebViewPage> { late final WebViewController controller; void initState() { super.initState(); controller = WebViewController() ..setJavaScriptMode(JavaScriptMode.unrestricted) ..setNavigationDelegate( NavigationDelegate( onNavigationRequest: (request) { final uri = Uri.tryParse(request.url); if (uri == null) { return NavigationDecision.prevent; } const allowedHosts = { 'example.com', 'allowed.example.com', }; if (allowedHosts.contains(uri.host)) { return NavigationDecision.navigate; } return NavigationDecision.prevent; }, ), ) ..loadRequest( Uri.parse('https://example.com'), ); } Widget build(BuildContext context) { return Scaffold( body: WebViewWidget( controller: controller, ), ); } }