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
3 changes: 2 additions & 1 deletion lib/web_ui/lib/src/engine/canvaskit/canvaskit_api.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3596,7 +3596,8 @@ Future<void> _downloadOneOf(Iterable<String> urls) async {
/// Returns a [Future] that completes with `true` if the CanvasKit JavaScript
/// file was successfully downloaded, or `false` if it failed.
Future<bool> _downloadCanvasKitJs(String url) {
final DomHTMLScriptElement canvasKitScript = createDomHTMLScriptElement();
final DomHTMLScriptElement canvasKitScript =
createDomHTMLScriptElement(configuration.nonce);
canvasKitScript.src = createTrustedScriptUrl(url);

final Completer<bool> canvasKitLoadCompleter = Completer<bool>();
Expand Down
9 changes: 9 additions & 0 deletions lib/web_ui/lib/src/engine/configuration.dart
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,11 @@ class FlutterConfiguration {
/// to render, or `null` if the user hasn't specified anything.
DomElement? get hostElement => _configuration?.hostElement;

/// Returns a `nonce` to allowlist the inline styles that Flutter web needs.
///
/// See: https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/nonce
String? get nonce => _configuration?.nonce;

/// Returns the [requestedRendererType] to be used with the current Flutter
/// application, normally 'canvaskit' or 'auto'.
///
Expand Down Expand Up @@ -320,6 +325,10 @@ extension JsFlutterConfigurationExtension on JsFlutterConfiguration {

external DomElement? get hostElement;

@JS('nonce')
external JSString? get _nonce;
String? get nonce => _nonce?.toDart;

@JS('renderer')
external JSString? get _renderer;
String? get renderer => _renderer?.toDart;
Expand Down
32 changes: 28 additions & 4 deletions lib/web_ui/lib/src/engine/dom.dart
Original file line number Diff line number Diff line change
Expand Up @@ -929,10 +929,20 @@ extension DomHTMLScriptElementExtension on DomHTMLScriptElement {
external set _src(JSAny value);
set src(Object /* String|TrustedScriptURL */ value) =>
_src = value.toJSAnyShallow;

@JS('nonce')
external set _nonce(JSString? value);
set nonce(String? value) => _nonce = value?.toJS;
}

DomHTMLScriptElement createDomHTMLScriptElement() =>
domDocument.createElement('script') as DomHTMLScriptElement;
DomHTMLScriptElement createDomHTMLScriptElement(String? nonce) {
final DomHTMLScriptElement script =
domDocument.createElement('script') as DomHTMLScriptElement;
if (nonce != null) {
script.nonce = nonce;
}
return script;
}

@JS()
@staticInterop
Expand Down Expand Up @@ -971,11 +981,25 @@ extension DomHTMLStyleElementExtension on DomHTMLStyleElement {
external set _type(JSString? value);
set type(String? value) => _type = value?.toJS;

@JS('nonce')
external set _nonce(JSString? value);
set nonce(String? value) => _nonce = value?.toJS;

@JS('nonce')
external JSString? get _nonce;
String? get nonce => _nonce?.toDart;

external DomStyleSheet? get sheet;
}

DomHTMLStyleElement createDomHTMLStyleElement() =>
domDocument.createElement('style') as DomHTMLStyleElement;
DomHTMLStyleElement createDomHTMLStyleElement(String? nonce) {
final DomHTMLStyleElement style =
domDocument.createElement('style') as DomHTMLStyleElement;
if (nonce != null) {
style.nonce = nonce;
}
return style;
}

@JS()
@staticInterop
Expand Down
8 changes: 4 additions & 4 deletions lib/web_ui/lib/src/engine/embedder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ class FlutterViewEmbedder {
});
_glassPaneShadow = shadowRoot;

final DomHTMLStyleElement shadowRootStyleElement = createDomHTMLStyleElement();
final DomHTMLStyleElement shadowRootStyleElement = createDomHTMLStyleElement(configuration.nonce);
shadowRootStyleElement.id = 'flt-internals-stylesheet';
// The shadowRootStyleElement must be appended to the DOM, or its `sheet` will be null later.
shadowRoot.appendChild(shadowRootStyleElement);
Expand All @@ -198,7 +198,7 @@ class FlutterViewEmbedder {
);

_textEditingHostNode =
createTextEditingHostNode(flutterViewElement, defaultCssFont);
createTextEditingHostNode(flutterViewElement, defaultCssFont, configuration.nonce);

// Don't allow the scene to receive pointer events.
_sceneHostElement = domDocument.createElement('flt-scene-host')
Expand Down Expand Up @@ -434,10 +434,10 @@ FlutterViewEmbedder ensureFlutterViewEmbedderInitialized() =>

/// Creates a node to host text editing elements and applies a stylesheet
/// to Flutter nodes that exist outside of the shadowDOM.
DomElement createTextEditingHostNode(DomElement root, String defaultFont) {
DomElement createTextEditingHostNode(DomElement root, String defaultFont, String? nonce) {
final DomElement domElement =
domDocument.createElement('flt-text-editing-host');
final DomHTMLStyleElement styleElement = createDomHTMLStyleElement();
final DomHTMLStyleElement styleElement = createDomHTMLStyleElement(nonce);

styleElement.id = 'flt-text-editing-stylesheet';
root.appendChild(styleElement);
Expand Down
10 changes: 9 additions & 1 deletion lib/web_ui/test/engine/global_styles_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,25 @@ void testMain() {
late DomHTMLStyleElement styleElement;

setUp(() {
styleElement = createDomHTMLStyleElement();
styleElement = createDomHTMLStyleElement(null);
domDocument.body!.append(styleElement);
applyGlobalCssRulesToSheet(
styleElement,
defaultCssFont: _kDefaultCssFont,
);
});

tearDown(() {
styleElement.remove();
});

test('createDomHTMLStyleElement sets a nonce value, when passed', () {
expect(styleElement.nonce, isEmpty);

final DomHTMLStyleElement style = createDomHTMLStyleElement('a-nonce-value');
expect(style.nonce, 'a-nonce-value');
});

test('(Self-test) hasCssRule can extract rules', () {
final bool hasRule = hasCssRule(styleElement,
selector: '.flt-text-editing::placeholder', declaration: 'opacity: 0');
Expand Down