Add extra polyfill for .nonce in our deferred loading logic to support FF

Firefox doesn't support the nonce IDL property ([Bugzilla](https://bugzilla.mozilla.org/show_bug.cgi?id=1389421)), so we read and set both the property and attribute to ensure the attribute is set. Because users may access .nonce from dart:html, we also read and set the property.

Fixes: #35783

Closes #35784
https://github.com/dart-lang/sdk/pull/35784

GitOrigin-RevId: 2e75c58901c9415cf13018070f8bbdc1dd58055c
Change-Id: I715fb502da676f8f2e3565774baa9d8dd609a485
Reviewed-on: https://dart-review.googlesource.com/c/91280
Commit-Queue: Stephen Adams <sra@google.com>
Reviewed-by: Stephen Adams <sra@google.com>
This commit is contained in:
Sigmund Cherem 2019-01-29 23:35:59 +00:00 committed by commit-bot@chromium.org
parent 1e92b5ebd0
commit b5d9e66963
3 changed files with 47 additions and 3 deletions

View file

@ -3353,7 +3353,10 @@ String _cspNonce = _computeCspNonce();
String _computeCspNonce() {
var currentScript = JS_EMBEDDED_GLOBAL('', CURRENT_SCRIPT);
if (currentScript == null) return null;
return JS('String', 'String(#.nonce)', currentScript);
String nonce = JS('String|Null', '#.nonce', currentScript);
return (nonce != null && nonce != '')
? nonce
: JS('String|Null', '#.getAttribute("nonce")', currentScript);
}
/// The 'crossOrigin' value on the current script used for CORS, if any.
@ -3509,6 +3512,7 @@ Future<Null> _loadHunk(String hunkName) {
JS('', '#.src = #', script, uri);
if (_cspNonce != null && _cspNonce != '') {
JS('', '#.nonce = #', script, _cspNonce);
JS('', '#.setAttribute("nonce", #)', script, _cspNonce);
}
if (_crossOrigin != null && _crossOrigin != '') {
JS('', '#.crossOrigin = #', script, _crossOrigin);

View file

@ -0,0 +1,38 @@
// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// Test that code loaded via deferred imports uses the same nonce value as the
// main page.
import "deferred_with_csp_nonce_lib.dart" deferred as lib;
import "package:expect/expect.dart";
import "package:async_helper/async_helper.dart";
import "dart:html";
main() {
asyncStart();
var scripts = document
.querySelectorAll<ScriptElement>('script')
.where((s) => s.src.contains("generated_compilations"))
.toList();
Expect.equals(1, scripts.length);
Expect.equals('', scripts.first.nonce ?? '');
Expect.equals('', scripts.first.getAttribute('nonce') ?? '');
scripts.first.setAttribute("nonce", "an-example-nonce-string");
lib.loadLibrary().then((_) {
print(lib.foo());
var scripts = document
.querySelectorAll<ScriptElement>('script')
.where((s) => s.src.contains(".part.js"))
.toList();
Expect.equals(1, scripts.length);
for (var script in scripts) {
Expect.equals("an-example-nonce-string", script.nonce);
Expect.equals("an-example-nonce-string", script.getAttribute('nonce'));
}
asyncEnd();
});
}

View file

@ -19,17 +19,19 @@ main() {
.toList();
Expect.equals(1, scripts.length);
Expect.equals('', scripts.first.nonce ?? '');
Expect.equals('', scripts.first.getAttribute('nonce') ?? '');
scripts.first.nonce = "an-example-nonce-string";
lib.loadLibrary().then((_) {
print(lib.foo());
var scripts = document
.querySelectorAll<ScriptElement>('script')
.where((s) => s.src.contains("generated_compilations"))
.where((s) => s.src.contains(".part.js"))
.toList();
Expect.equals(2, scripts.length);
Expect.equals(1, scripts.length);
for (var script in scripts) {
Expect.equals("an-example-nonce-string", script.nonce);
Expect.equals("an-example-nonce-string", script.getAttribute('nonce'));
}
asyncEnd();
});