Skip to content

[Webview] Headers on android webview are not shared to redirected page when using NavigationDelegate #169588

Open
@EArminjon

Description

@EArminjon

Steps to reproduce

  1. Run app
  2. See the 'Issue' page

Expected results

On Android : Issue page should work without any tricks.

Actual results

On Android : Issue page can't be loaded because NavigationDelegate.onNavigationRequest has been set and so headers are not persisted when the url is redirect to an other one of the same domain.

Code sample

  webview_flutter: 4.13.0
  webview_flutter_android: 4.7.0
  webview_flutter_wkwebview: 3.22.0
Code sample
import 'dart:async';

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'package:webview_flutter_android/webview_flutter_android.dart';
import 'package:webview_flutter_wkwebview/webview_flutter_wkwebview.dart';

void main() {
  runApp(const MaterialApp(home: Home()));
}

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

  @override
  State<Home> createState() => _HomeState();
}

class _HomeState extends State<Home> {
  int index = 0;

  @override
  Widget build(final BuildContext context) {
    return Scaffold(
      body: IndexedStack(
        index: index,
        children: <Widget>[
          const CustomWebview(
            url: 'https://httpbin.org/redirect-to?url=/bearer',
            enableNavigationDelegate: true,
          ),
          const CustomWebview(
            url: 'https://httpbin.org/redirect-to?url=/bearer',
            enableNavigationDelegate: false,
          ),
        ],
      ),
      bottomNavigationBar: NavigationBar(
        selectedIndex: index,
        onDestinationSelected:
            (final int selected) => setState(() => index = selected),
        destinations: <Widget>[
          const NavigationDestination(
            label: 'Issue',
            icon: Icon(Icons.close, color: Colors.red),
          ),
          const NavigationDestination(
            label: 'No issue',
            icon: Icon(Icons.check, color: Colors.green),
          ),
        ],
      ),
    );
  }
}

class CustomWebview extends StatefulWidget {
  const CustomWebview({
    super.key,
    required this.url,
    required this.enableNavigationDelegate,
  });

  final String url;
  final bool enableNavigationDelegate;

  @override
  State<CustomWebview> createState() => _CustomWebview();
}

class _CustomWebview extends State<CustomWebview> {
  late final WebViewController _controller;
  bool loading = false;

  @override
  void initState() {
    final PlatformWebViewControllerCreationParams params;
    if (WebViewPlatform.instance is WebKitWebViewPlatform) {
      params = WebKitWebViewControllerCreationParams(
        allowsInlineMediaPlayback: true,
        mediaTypesRequiringUserAction: PlaybackMediaTypes.values.toSet(),
      );
    } else if (WebViewPlatform.instance is AndroidWebViewPlatform) {
      params = AndroidWebViewControllerCreationParams();
    } else {
      params = const PlatformWebViewControllerCreationParams();
    }

    final WebViewController controller =
        WebViewController.fromPlatformCreationParams(params);

    controller
      ..clearCache()
      ..setJavaScriptMode(JavaScriptMode.unrestricted)
      ..setBackgroundColor(Colors.white)
      ..setOverScrollMode(WebViewOverScrollMode.never)
      ..enableZoom(false);

    if (widget.enableNavigationDelegate) {
      controller.setNavigationDelegate(
        NavigationDelegate(
          onNavigationRequest: _onNavigationRequest,
          onProgress: (final int value) {
            setState(() => loading = value < 100);
          },
          onHttpError: (final HttpResponseError error) {
            print("${error.request?.uri} ${error.response?.statusCode}");
          },
        ),
      );
    }

    if (controller.platform is WebKitWebViewController) {
    } else if (controller.platform is AndroidWebViewController) {
      AndroidWebViewController.enableDebugging(kDebugMode);
      (controller.platform as AndroidWebViewController)
          .setMediaPlaybackRequiresUserGesture(true);
    }

    controller.loadRequest(
      Uri.parse(widget.url),
      headers: <String, String>{'Authorization': 'Bearer 12345'},
    );

    _controller = controller;

    super.initState();
  }

  FutureOr<NavigationDecision> _onNavigationRequest(
    final NavigationRequest request,
  ) async {
    if (kDebugMode) print(request.url);
    return NavigationDecision.navigate;
  }

  @override
  Widget build(final BuildContext context) {
    late final Widget webViewWidget;
    if (WebViewPlatform.instance is AndroidWebViewPlatform) {
      webViewWidget = WebViewWidget.fromPlatformCreationParams(
        params: AndroidWebViewWidgetCreationParams(
          controller: _controller.platform,
          displayWithHybridComposition: true,
        ),
      );
    } else {
      webViewWidget = WebViewWidget(controller: _controller);
    }

    return GestureDetector(
      onTap: () => FocusScope.of(context).unfocus(),
      child: Scaffold(
        appBar: AppBar(
          title: const Text("Header issue"),
          actions: <Widget>[
            IconButton(
              onPressed: () {
                _controller.reload();
              },
              icon: const Icon(Icons.refresh),
            ),
          ],
        ),
        backgroundColor: Colors.white,
        body: SafeArea(
          child: Stack(
            children: <Widget>[
              webViewWidget,
              if (loading) const Center(child: CircularProgressIndicator()),
            ],
          ),
        ),
      ),
    );
  }
}

Screenshots or Video

Screenshots / Video demonstration
Image Image

Logs

Logs
Performing hot restart...
Syncing files to device sdk gphone64 x86 64...
Restarted application in 1 427ms.
D/EGL_emulation( 4633): app_time_stats: avg=6004.60ms min=21.84ms max=53675.92ms count=9
E/libEGL  ( 4633): called unimplemented OpenGL ES API
D/EGL_emulation( 4633): app_time_stats: avg=6283.95ms min=55.17ms max=55815.22ms count=9
I/PlatformViewsController( 4633): Using hybrid composition for platform view: 0
I/PlatformViewsController( 4633): Using hybrid composition for platform view: 1
D/EGL_emulation( 4633): app_time_stats: avg=1421.17ms min=1421.17ms max=1421.17ms count=1
D/EGL_emulation( 4633): app_time_stats: avg=6307.30ms min=55.27ms max=56021.62ms count=9
I/flutter ( 4633): https://httpbin.org/bearer
I/tal.generations( 4633): NativeAlloc concurrent mark compact GC freed 842KB AllocSpace bytes, 2(32KB) LOS objects, 49% free, 7330KB/14MB, paused 735us,9.208ms total 40.763ms
I/flutter ( 4633): https://httpbin.org/bearer 401
E/libEGL  ( 4633): called unimplemented OpenGL ES API
D/EGL_emulation( 4633): app_time_stats: avg=118.36ms min=28.05ms max=345.47ms count=11

Flutter Doctor output

Doctor output
[√] Flutter (Channel stable, 3.32.0, on Microsoft Windows [version 10.0.22631.5039], locale fr-FR) [590ms]
    • Flutter version 3.32.0 on channel stable at C:\Users\engue\fvm\versions\3.32.0
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision be698c48a6 (9 days ago), 2025-05-19 12:59:14 -0700
    • Engine revision 1881800949
    • Dart version 3.8.0
    • DevTools version 2.45.1

[√] Windows Version (11 Professionnel 64-bit, 23H2, 2009) [6,5s]

[√] Android toolchain - develop for Android devices (Android SDK version 35.0.0) [2,8s]
    • Android SDK at D:\Android
    • Platform android-35, build-tools 35.0.0
    • Java binary at: C:\Users\engue\.jdks\corretto-17.0.13\bin\java
      This JDK is specified in your Flutter configuration.
      To change the current JDK, run: `flutter config --jdk-dir="path/to/jdk"`.
    • Java version OpenJDK Runtime Environment Corretto-17.0.13.11.1 (build 17.0.13+11-LTS)
    • All Android licenses accepted.

[√] Chrome - develop for the web [217ms]
    • Chrome at C:\Program Files (x86)\Google\Chrome\Application\chrome.exe

[√] Visual Studio - develop Windows apps (Visual Studio Community 2019 16.11.45) [216ms]
    • Visual Studio at D:\dev
    • Visual Studio Community 2019 version 16.11.35826.135
    • Windows 10 SDK version 10.0.22621.0

[√] Android Studio (version 2024.3.2) [144ms]
    • Android Studio at C:\Users\engue\AppData\Local\Programs\Android Studio
    • Flutter plugin can be installed from:
       https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
       https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 21.0.6+-13368085-b895.109)

[√] IntelliJ IDEA Ultimate Edition (version 2025.1) [142ms]
    • IntelliJ at C:\Users\engue\AppData\Local\Programs\IntelliJ IDEA Ultimate
    • Flutter plugin version 85.3.2
    • Dart plugin version 251.25410.28

[√] Connected device (4 available) [428ms]
    • sdk gphone64 x86 64 (mobile) • emulator-5554 • android-x64    • Android 15 (API 35) (emulator)
    • Windows (desktop)            • windows       • windows-x64    • Microsoft Windows [version 10.0.22631.5039]
    • Chrome (web)                 • chrome        • web-javascript • Google Chrome 136.0.7103.114
    • Edge (web)                   • edge          • web-javascript • Microsoft Edge 135.0.3179.98

[√] Network resources [387ms]
    • All expected network resources are available.

• No issues found!

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Important issues not at the top of the work listc: new featureNothing broken; request for a new capabilityfound in release: 3.32Found to occur in 3.32found in release: 3.33Found to occur in 3.33has reproducible stepsThe issue has been confirmed reproducible and is ready to work onp: webviewThe WebView pluginpackageflutter/packages repository. See also p: labels.platform-androidAndroid applications specificallyteam-androidOwned by Android platform teamtriaged-androidTriaged by Android platform team

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions