| // Copyright (c) 2019, 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. |
| |
| import 'dart:js_interop'; |
| import 'package:web/web.dart'; |
| |
| // According to the CSP3 spec a nonce must be a valid base64 string. |
| final _noncePattern = RegExp('^[\\w+/_-]+[=]{0,2}\$'); |
| |
| /// Returns CSP nonce, if set for any script tag. |
| String? _findNonce() { |
| final elements = window.document.querySelectorAll('script'); |
| |
| for (var i = 0; i < elements.length; i++) { |
| final element = elements.item(i); |
| final nonceValue = (element as HTMLElement).nonce; |
| if (_noncePattern.hasMatch(nonceValue)) { |
| return nonceValue; |
| } |
| } |
| return null; |
| } |
| |
| /// Creates a script that will run properly when strict CSP is enforced. |
| /// |
| /// More specifically, the script has the correct `nonce` value set. |
| final HTMLElement Function() _createScript = |
| (() { |
| final nonce = _findNonce(); |
| |
| if (nonce == null) { |
| return () => document.createElement('script') as HTMLElement; |
| } |
| return () { |
| final scriptElement = document.createElement('script') as HTMLElement; |
| return scriptElement..setAttribute('nonce', nonce); |
| }; |
| })(); |
| |
| /// Runs `window.$dartRunMain()` by injecting a script tag. |
| /// |
| /// We do this so that we don't see user exceptions bubble up in our own error |
| /// handling zone. |
| void runMain() { |
| final scriptElement = |
| _createScript()..innerHTML = r'window.$dartRunMain();'.toJS; |
| document.body!.append(scriptElement.jsify()!); |
| // External tear-offs are not allowed. |
| // ignore: unnecessary_lambdas |
| Future.microtask(() => scriptElement.remove()); |
| } |