flutter_chromium_webview 0.5.3 copy "flutter_chromium_webview: ^0.5.3" to clipboard
flutter_chromium_webview: ^0.5.3 copied to clipboard

Chromium webview for Windows, macOS and Linux using CEF textures, and Android using the system WebView, with browser events and origin-restricted channels.

flutter_chromium_webview #

A high-performance Chromium web view plugin for Flutter on Windows, macOS, Linux, and Android.

Desktop platforms bundle a pinned Chromium engine through CEF (Chromium Embedded Framework) with Off-Screen Rendering (OSR) directly into Flutter textures. Android integrates the system Chromium WebView using Flutter's hybrid composition platform view.

Target Release: 0.5.3
Companion platform interface: flutter_chromium_webview_platform_interface: ^0.1.6


Table of Contents #


Platform Support & Status #

Platform Engine Rendering Path Status Guide
macOS 13+ CEF 149 (Chromium 149) Accelerated IOSurface via Metal Supported (Apple Silicon arm64 & Intel x86_64) MACOS.md
Windows 10+ CEF 149 (Chromium 149) Software pixel buffer to Texture Supported (x64, sandboxed bootstrap runner) WINDOWS.md
Linux CEF 149 (Chromium 149) Software pixel buffer to Texture Supported (x64, X11 / XWayland via GTK3) LINUX.md
Android (API 24+) System Chromium WebView Native Platform View (Hybrid Composition) Supported (ARM64, ARM32, x86_64) ANDROID.md
iOS WebKit (WKWebView) Headless prototype Source only; not registered or supported IOS.md
Web N/A N/A Not implemented N/A

Architecture Overview #

On desktop operating systems, flutter_chromium_webview uses Off-Screen Rendering (OSR):

  1. Chromium renders web contents completely off-screen in background helper processes.
  2. Rendered frames are passed to native host callbacks:
    • On macOS, frames are delivered as hardware-accelerated IOSurface handles and bound to Metal textures.
    • On Windows and Linux, pixel buffers are copied into a retained frame buffer and registered with the Flutter Engine's texture registry.
  3. The browser appears in your Flutter widget tree as a regular Flutter Texture. It can be seamlessly clipped (e.g. ClipRRect), transformed, stacked, animated, or overlaid with other Flutter widgets.
  4. On Android, rendering uses Flutter's native platform view mechanism (Hybrid Composition), providing native Android touch handling, accessibility, and virtual keyboard interaction.

Requirements #

SDK Requirements #

  • Dart SDK: >=3.12.0 <4.0.0
  • Flutter SDK: >=3.44.0

The package is engineered to be compatible with Dart >=3.12.0, allowing applications using Flutter 3.44+ (such as PPPlayer) to consume the published package without version conflicts. CI strictly tests across Flutter 3.47.4 / Dart 3.13.3.

OS & Toolchain Requirements #

  • macOS: macOS 13 (Ventura) or newer, Xcode 15+, CMake 3.19+, Python 3, CocoaPods.
  • Windows: Windows 10/11 x64, Visual Studio 2022 (with C++ desktop development tools), CMake 3.19+.
  • Linux: Linux x64 with GTK 3, Clang, CMake 3.19+, Ninja, pkg-config, X11 or XWayland, PulseAudio.
  • Android: Android API 24+ (Android 7.0 Nougat), Android compile SDK 36, Java 17.

Installation & Setup #

Add the package to your pubspec.yaml:

dependencies:
  flutter_chromium_webview: ^0.5.3

Because desktop platforms require native runtime bootstrapping, follow the platform-specific instructions below:

macOS Configuration #

macOS requires host embedding and runner configuration outside Apple's App Sandbox. For complete instructions, see MACOS.md.

  1. In pubspec.yaml, disable Swift Package Manager for macOS:
    flutter:
      config:
        enable-swift-package-manager: false
    
  2. In macos/Runner/Info.plist, set NSPrincipalClass to ChromiumWebViewApplication.
  3. In macos/Runner/DebugProfile.entitlements and macos/Runner/Release.entitlements, set com.apple.security.app-sandbox to <false/>.
  4. Add the CEF preparation step to your macos/Podfile and the embedding script to your Xcode Runner build phase as detailed in MACOS.md.

Windows Configuration #

Windows uses CEF's sandboxed bootstrap executable runner. For complete instructions, see WINDOWS.md.

  1. In windows/runner/CMakeLists.txt, change the runner target to a shared library (add_library(${BINARY_NAME} SHARED ...)).
  2. In windows/CMakeLists.txt, add chromium_webview_enable_sandbox(${BINARY_NAME}).
  3. In windows/runner/main.cpp, export RunWinMain as described in WINDOWS.md.

Linux Configuration #

Ensure system packages are installed:

sudo apt-get install -y clang cmake ninja-build pkg-config libgtk-3-dev pulseaudio

On first build, CMake automatically downloads and verifies the pinned CEF Linux distribution. See LINUX.md.

Android Configuration #

Ensure your android/app/build.gradle has minSdkVersion 24 and Java 17 compatibility. Internet permission is included automatically by the plugin manifest. See ANDROID.md.


Quick Start #

Initialize the CEF runtime once in main() before creating any browser:

import 'package:flutter/material.dart';
import 'package:flutter_chromium_webview/flutter_chromium_webview.dart';
import 'package:path_provider/path_provider.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  
  // Initialize CEF runtime on desktop. On Android, this initializes the WebView provider.
  final cache = await getApplicationSupportDirectory();
  final initialized = await ChromiumWebViewController.initialize(
    cachePath: cache.path,
  );
  if (!initialized) {
    throw StateError('Failed to initialize Chromium runtime');
  }

  runApp(const MaterialApp(home: WebViewDemo()));
}

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

  @override
  State<WebViewDemo> createState() => _WebViewDemoState();
}

class _WebViewDemoState extends State<WebViewDemo> {
  final controller = ChromiumWebViewController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Chromium WebView')),
      body: ChromiumWebView(
        controller: controller,
        initialUrl: 'https://flutter.dev',
      ),
    );
  }
}

Core Features & Usage #

Lifecycle Management #

By default, the ChromiumWebView widget automatically disposes its controller when removed from the widget tree. If you want to keep the controller alive while navigating between tabs or screens, pass disposeController: false:

ChromiumWebView(
  controller: controller,
  disposeController: false, // You manage disposal explicitly
  initialUrl: 'https://flutter.dev',
);

When you are done with the controller:

await controller.dispose();
// Load an arbitrary URL
await controller.loadUrl('https://dart.dev');

// Load raw HTML with an explicit base URL for origin and relative assets
await controller.loadHtmlString(
  '<h1>Hello from Flutter!</h1><p>Running on Chromium.</p>',
  baseUrl: 'https://example.com/app/',
);

// Navigation controls
if (controller.canGoBack) await controller.goBack();
if (controller.canGoForward) await controller.goForward();
await controller.reload();
await controller.stopLoading();

The controller extends ChangeNotifier, notifying listeners on URL changes, title changes, and progress updates:

ListenableBuilder(
  listenable: controller,
  builder: (context, _) {
    return Text(controller.pageTitle ?? controller.currentUrl ?? 'Loading...');
  },
);

JavaScript Evaluation & Execution #

Execute fire-and-forget scripts or evaluate expressions and receive structured results:

// Fire-and-forget
await controller.executeJavaScript("console.log('Hello from Dart');");

// Evaluate expression with returned value
try {
  final result = await controller.evaluateJavaScript('document.title');
  print('Page title: $result');

  // Objects and arrays are returned as parsed JSON structures
  final dimensions = await controller.evaluateJavaScript('''
    ({
      width: window.innerWidth,
      height: window.innerHeight,
      userAgent: navigator.userAgent
    })
  ''');
  print('Window info: $dimensions');
} catch (e) {
  print('JavaScript execution error: $e');
}

Two-Way JavaScript Bridge #

Communicate securely from web content back to Flutter using origin-restricted JavaScriptChannels:

final channel = JavaScriptChannel(
  name: 'FlutterBridge',
  allowedOrigins: {'https://flutter.dev', 'https://dart.dev'},
  onMessageReceived: (JavaScriptMessage msg) {
    print('Received message: ${msg.message}');
  },
);

final controller = ChromiumWebViewController(
  javaScriptChannels: [channel],
);

In the webpage JavaScript:

// Send a message to Flutter
FlutterBridge.postMessage(JSON.stringify({ event: 'button_clicked', id: 42 }));

Messages are protected by strict origin allowlists and capped at a maximum of 64 KiB UTF-8 to prevent buffer exhaustion.

Cookies, Storage & Named Profiles #

Configure isolation, cookies, user-agent, and media gesture policies at controller construction:

final controller = ChromiumWebViewController(
  profileName: 'isolated_user_profile', // Dedicated storage partition
  userAgent: 'MyCustomApp/1.0 (Flutter Desktop)',
  mediaPlaybackRequiresUserGesture: false, // Enable autoplay
  backgroundColor: const Color(0xFF1E1E1E), // Dark canvas during navigation
);
  • When profileName is omitted, the browser shares the global cache and cookie store.
  • Setting mediaPlaybackRequiresUserGesture: false creates an ephemeral private context suitable for media playback without polluting persistent sessions.

Multiple Simultaneous WebViews #

You can run multiple independent WebView instances simultaneously. Each has its own texture, controller, and event dispatching:

Row(
  children: [
    Expanded(child: ChromiumWebView(controller: controllerA, initialUrl: 'https://flutter.dev')),
    const VerticalDivider(),
    Expanded(child: ChromiumWebView(controller: controllerB, initialUrl: 'https://dart.dev')),
  ],
)

Input, Focus & Keyboard #

  • Mouse / Pointer: Coordinates, high-DPI device pixel ratios, scroll wheels, and multi-click counts (double-clicks, triple-clicks) are forwarded automatically to the native browser.
  • Keyboard & Shortcuts: Key events, Cmd/Ctrl editing shortcuts (Copy, Cut, Paste, Select All), and IME composition are handled natively.

JavaScript Dialogs & Context Menus #

Customize the presentation of JavaScript dialogs (alert, confirm, prompt) and right-click context menus using Flutter UI:

controller.onJSDialog = (JSDialogRequest request) async {
  final confirmed = await showDialog<bool>(
    context: context,
    builder: (ctx) => AlertDialog(
      title: Text(request.type.name.toUpperCase()),
      content: Text(request.message),
      actions: [
        TextButton(onPressed: () => Navigator.pop(ctx, false), child: const Text('Cancel')),
        FilledButton(onPressed: () => Navigator.pop(ctx, true), child: const Text('OK')),
      ],
    ),
  );
  return JSDialogResponse(success: confirmed ?? false);
};

controller.onContextMenu = (List<ContextMenuItem> items) {
  // Render Flutter popup or context menu using the provided command IDs
};

New Window Interception #

Intercept window.open or target _blank links:

controller.onNewWindowRequested = (NewWindowRequest request) {
  print('Requested popup URL: ${request.url}');
  // Open in a new tab, dialog, or external browser
};

YouTube & Video Playback Integration #

For video playback, the plugin includes a dedicated ChromiumYoutubePlayerController that wraps YouTube's IFrame API with native telemetry, autoplay support, and state synchronization:

import 'package:flutter_chromium_webview/chromium_youtube_player.dart';

final player = ChromiumYoutubePlayerController(
  documentUrl: 'https://example.com/player',
  readyTimeout: const Duration(seconds: 15),
);

// In your widget:
ChromiumWebView(
  controller: player.webViewController,
  disposeController: false,
);

// Control playback:
await player.loadVideoById('dQw4w9WgXcQ');
await player.play();
await player.pause();
await player.seekTo(Duration(seconds: 45));

Supported open video codecs: VP8, VP9, AV1, Vorbis, Opus. Standard CEF does not include proprietary codecs like H.264 or AAC.

Crash Recovery & Fault Tolerance #

If the Chromium renderer or GPU subprocess crashes, flutter_chromium_webview detects the failure and fires onBrowserCrashed:

controller.onBrowserCrashed = () {
  ScaffoldMessenger.of(context).showSnackBar(
    const SnackBar(content: Text('Browser process crashed. Reloading...')),
  );
  controller.reload();
};

Troubleshooting & Known Limitations #

  • Proprietary Codecs: Stock CEF builds distributed by the project do not include H.264 or AAC codecs due to patent and licensing restrictions. Media encoded with VP8, VP9, or AV1 is recommended.
  • Apple App Sandbox: The macOS CEF backend currently requires direct distribution outside Apple's App Sandbox. See MACOS.md.
  • Process Shutdown: Once CEF has shut down via CefShutdown(), CEF cannot be reinitialized in the same process without restarting the host application.
  • macOS Memory Bounds: Extended validation confirms clean tracked resource disposal and zero surviving processes on shutdown. However, long-term leak freedom and physical 8 GB qualification remain open product items.
  • Application Bundle Size: Bundling Chromium and CEF increases the application distribution size by approximately 100–130 MB.

Packages in this Repository #


Contributing & License #

Contributions are welcome! Please review CONTRIBUTING.md and docs/architecture.md.

This project is licensed under the MIT License.
Chromium and CEF are covered by their respective BSD-style licenses.

1
likes
0
points
838
downloads

Publisher

verified publisherdevflier.com

Weekly Downloads

Chromium webview for Windows, macOS and Linux using CEF textures, and Android using the system WebView, with browser events and origin-restricted channels.

Homepage
Repository (GitHub)
View/report issues

Topics

#flutter #desktop #webview #cef #chromium

License

unknown (license)

Dependencies

flutter, flutter_chromium_webview_platform_interface

More

Packages that depend on flutter_chromium_webview

Packages that implement flutter_chromium_webview