Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
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: 3 additions & 1 deletion lib/web_ui/lib/src/engine/browser_detection.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import 'package:meta/meta.dart';

import 'dom.dart';
import 'safe_browser_api.dart';

// iOS 15 launched WebGL 2.0, but there's something broken about it, which
// leads to apps failing to load. For now, we're forcing WebGL 1 on iOS.
Expand Down Expand Up @@ -268,4 +269,5 @@ int _detectWebGLVersion() {
}

/// Whether the current browser supports the Chromium variant of CanvasKit.
final bool browserSupportsCanvaskitChromium = domIntl.v8BreakIterator != null;
bool get browserSupportsCanvaskitChromium =>
browserSupportsImageDecoder && domIntl.v8BreakIterator != null;
1 change: 1 addition & 0 deletions lib/web_ui/lib/src/engine/canvaskit/canvaskit_api.dart
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import 'renderer.dart';
late CanvasKit canvasKit;

// TODO(mdebbar): Turn this on when CanvasKit Chromium is ready.
// Set it to `browserSupportsCanvasKitChromium`.
// https://github.com/flutter/flutter/issues/122329
const bool _enableCanvasKitChromiumInAutoMode = false;

Expand Down
22 changes: 16 additions & 6 deletions lib/web_ui/lib/src/engine/safe_browser_api.dart
Original file line number Diff line number Diff line change
Expand Up @@ -217,17 +217,27 @@ const bool _browserImageDecodingEnabled = bool.fromEnvironment(
);

/// Whether the current browser supports `ImageDecoder`.
bool browserSupportsImageDecoder =
_browserImageDecodingEnabled &&
_imageDecoderConstructor != null &&
browserEngine == BrowserEngine.blink;
bool browserSupportsImageDecoder = _defaultBrowserSupportsImageDecoder;

/// Sets the value of [browserSupportsImageDecoder] to its default value.
void debugResetBrowserSupportsImageDecoder() {
browserSupportsImageDecoder =
_imageDecoderConstructor != null;
browserSupportsImageDecoder = _defaultBrowserSupportsImageDecoder;
}

bool get _defaultBrowserSupportsImageDecoder =>
_browserImageDecodingEnabled &&
_imageDecoderConstructor != null &&
_isBrowserImageDecoderStable;

// TODO(yjbanov): https://github.com/flutter/flutter/issues/122761
// Frequently, when a browser launches an API that other browsers already
// support, there are subtle incompatibilities that may cause apps to crash if,
// we blindly adopt the new implementation. This variable prevents us from
// picking up potentially incompatible implementations of ImagdeDecoder API.
// Instead, when a new browser engine launches the API, we'll evaluate it and
// enable it explicitly.
bool get _isBrowserImageDecoderStable => browserEngine == BrowserEngine.blink;

/// The signature of the function passed to the constructor of JavaScript `Promise`.
typedef JsPromiseCallback = void Function(void Function(Object? value) resolve, void Function(Object? error) reject);

Expand Down
49 changes: 49 additions & 0 deletions lib/web_ui/test/browser_detect_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'package:js/js.dart';

import 'package:test/bootstrap/browser.dart';
import 'package:test/test.dart';
import 'package:ui/src/engine/browser_detection.dart';
import 'package:ui/src/engine/safe_browser_api.dart';

void main() {
internalBootstrapBrowserTest(() => testMain);
Expand Down Expand Up @@ -152,4 +155,50 @@ void testMain() {
);
});
});

group('browserSupportsCanvasKitChromium', () {
late dynamic oldV8BreakIterator = v8BreakIterator;
setUp(() {
oldV8BreakIterator = v8BreakIterator;
});
tearDown(() {
v8BreakIterator = oldV8BreakIterator;
debugResetBrowserSupportsImageDecoder();
});

test('Detect browsers that support CanvasKit Chromium', () {
v8BreakIterator = Object(); // Any non-null value.
browserSupportsImageDecoder = true;

expect(browserSupportsCanvaskitChromium, isTrue);
});

test('Detect browsers that do not support image codecs', () {
v8BreakIterator = Object(); // Any non-null value.
browserSupportsImageDecoder = false;

expect(browserSupportsCanvaskitChromium, isFalse);
});

test('Detect browsers that do not support v8BreakIterator', () {
v8BreakIterator = null;
browserSupportsImageDecoder = true;

expect(browserSupportsCanvaskitChromium, isFalse);
});

test('Detect browsers that support neither', () {
v8BreakIterator = null;
browserSupportsImageDecoder = false;

expect(browserSupportsCanvaskitChromium, isFalse);
});
});
}


@JS('window.Intl.v8BreakIterator')
external dynamic get v8BreakIterator;

@JS('window.Intl.v8BreakIterator')
external set v8BreakIterator(dynamic x);
13 changes: 13 additions & 0 deletions third_party/canvaskit/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,14 @@ import("//build/toolchain/wasm.gni")
# This toolchain is only to be used by the canvaskit target below.
wasm_toolchain("canvaskit") {
extra_toolchain_args = {
# Include ICU data.
skia_use_icu = true
skia_use_client_icu = false

# Include image codecs.
skia_use_libjpeg_turbo_decode = true
skia_use_libpng_decode = true
skia_use_libwebp_decode = true
}
}

Expand All @@ -20,9 +26,16 @@ group("canvaskit_group") {
# This toolchain is only to be used by canvaskit_chromium_group below.
wasm_toolchain("canvaskit_chromium") {
extra_toolchain_args = {
# In Chromium browsers, we can use the browser's APIs to get the necessary
# ICU data.
skia_use_icu = false
skia_use_client_icu = true
skia_icu_bidi_third_party_dir = "//flutter/third_party/canvaskit/icu_bidi"

# In Chromium browsers, we can use the browser's built-in codecs.
skia_use_libjpeg_turbo_decode = false
skia_use_libpng_decode = false
skia_use_libwebp_decode = false
}
}

Expand Down
5 changes: 2 additions & 3 deletions tools/gn
Original file line number Diff line number Diff line change
Expand Up @@ -617,11 +617,10 @@ def to_gn_wasm_args(args, gn_args):
gn_args['skia_use_vulkan'] = False
gn_args['skia_use_webgpu'] = False
gn_args['skia_use_libheif'] = False
gn_args['skia_use_libjpeg_turbo_decode'] = True
gn_args['skia_use_libjpeg_turbo_encode'] = False
gn_args['skia_use_libpng_decode'] = True
# TODO(yjbanov): https://github.com/flutter/flutter/issues/122759
# Remove this and implement it through Canvas2d.
gn_args['skia_use_libpng_encode'] = True
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please file an issue to remove this as well? We can implement this by piping the image through a 2D canvas.

gn_args['skia_use_libwebp_decode'] = True
gn_args['skia_use_libwebp_encode'] = False
gn_args['skia_use_lua'] = False
gn_args['skia_use_wuffs'] = True
Expand Down