diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index 09c825e26c410..ae380c080e066 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -1893,7 +1893,6 @@ ORIGIN: ../../../flutter/lib/web_ui/lib/semantics.dart + ../../../flutter/LICENS ORIGIN: ../../../flutter/lib/web_ui/lib/src/engine.dart + ../../../flutter/LICENSE ORIGIN: ../../../flutter/lib/web_ui/lib/src/engine/alarm_clock.dart + ../../../flutter/LICENSE ORIGIN: ../../../flutter/lib/web_ui/lib/src/engine/app_bootstrap.dart + ../../../flutter/LICENSE -ORIGIN: ../../../flutter/lib/web_ui/lib/src/engine/assets.dart + ../../../flutter/LICENSE ORIGIN: ../../../flutter/lib/web_ui/lib/src/engine/browser_detection.dart + ../../../flutter/LICENSE ORIGIN: ../../../flutter/lib/web_ui/lib/src/engine/canvas_pool.dart + ../../../flutter/LICENSE ORIGIN: ../../../flutter/lib/web_ui/lib/src/engine/canvaskit/canvas.dart + ../../../flutter/LICENSE @@ -2109,6 +2108,7 @@ ORIGIN: ../../../flutter/lib/web_ui/lib/text.dart + ../../../flutter/LICENSE ORIGIN: ../../../flutter/lib/web_ui/lib/tile_mode.dart + ../../../flutter/LICENSE ORIGIN: ../../../flutter/lib/web_ui/lib/ui.dart + ../../../flutter/LICENSE ORIGIN: ../../../flutter/lib/web_ui/lib/ui_web/src/ui_web.dart + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/lib/web_ui/lib/ui_web/src/ui_web/asset_manager.dart + ../../../flutter/LICENSE ORIGIN: ../../../flutter/lib/web_ui/lib/ui_web/src/ui_web/navigation/platform_location.dart + ../../../flutter/LICENSE ORIGIN: ../../../flutter/lib/web_ui/lib/ui_web/src/ui_web/navigation/url_strategy.dart + ../../../flutter/LICENSE ORIGIN: ../../../flutter/lib/web_ui/lib/ui_web/src/ui_web/platform_view_registry.dart + ../../../flutter/LICENSE @@ -4572,7 +4572,6 @@ FILE: ../../../flutter/lib/web_ui/lib/semantics.dart FILE: ../../../flutter/lib/web_ui/lib/src/engine.dart FILE: ../../../flutter/lib/web_ui/lib/src/engine/alarm_clock.dart FILE: ../../../flutter/lib/web_ui/lib/src/engine/app_bootstrap.dart -FILE: ../../../flutter/lib/web_ui/lib/src/engine/assets.dart FILE: ../../../flutter/lib/web_ui/lib/src/engine/browser_detection.dart FILE: ../../../flutter/lib/web_ui/lib/src/engine/canvas_pool.dart FILE: ../../../flutter/lib/web_ui/lib/src/engine/canvaskit/canvas.dart @@ -4788,6 +4787,7 @@ FILE: ../../../flutter/lib/web_ui/lib/text.dart FILE: ../../../flutter/lib/web_ui/lib/tile_mode.dart FILE: ../../../flutter/lib/web_ui/lib/ui.dart FILE: ../../../flutter/lib/web_ui/lib/ui_web/src/ui_web.dart +FILE: ../../../flutter/lib/web_ui/lib/ui_web/src/ui_web/asset_manager.dart FILE: ../../../flutter/lib/web_ui/lib/ui_web/src/ui_web/navigation/platform_location.dart FILE: ../../../flutter/lib/web_ui/lib/ui_web/src/ui_web/navigation/url_strategy.dart FILE: ../../../flutter/lib/web_ui/lib/ui_web/src/ui_web/platform_view_registry.dart diff --git a/lib/web_ui/lib/initialization.dart b/lib/web_ui/lib/initialization.dart index 9ec0e8474a071..bf6b5f299306c 100644 --- a/lib/web_ui/lib/initialization.dart +++ b/lib/web_ui/lib/initialization.dart @@ -111,11 +111,18 @@ set debugEmulateFlutterTesterEnvironment(bool value) { bool _debugEmulateFlutterTesterEnvironment = false; /// Provides the asset manager. -// TODO(yjbanov): this function should not return a private type. Instead, we -// should create a public interface for the returned value that's -// implemented by the engine. -// https://github.com/flutter/flutter/issues/100394 -engine.AssetManager get webOnlyAssetManager => engine.assetManager; +// TODO(mdebbar): Deprecate this and remove it. +// https://github.com/flutter/flutter/issues/127395 +ui_web.AssetManager get webOnlyAssetManager { + assert(() { + engine.printWarning( + 'The webOnlyAssetManager getter is deprecated and will be removed in a ' + 'future release. Please use `assetManager` from `dart:ui_web` instead.', + ); + return true; + }()); + return ui_web.assetManager; +} /// Sets the handler that forwards platform messages to web plugins. /// diff --git a/lib/web_ui/lib/src/engine.dart b/lib/web_ui/lib/src/engine.dart index e5c92bfe21517..91ddf97bdec7d 100644 --- a/lib/web_ui/lib/src/engine.dart +++ b/lib/web_ui/lib/src/engine.dart @@ -17,7 +17,6 @@ library engine; export 'engine/alarm_clock.dart'; export 'engine/app_bootstrap.dart'; -export 'engine/assets.dart'; export 'engine/browser_detection.dart'; export 'engine/canvas_pool.dart'; export 'engine/canvaskit/canvas.dart'; diff --git a/lib/web_ui/lib/src/engine/canvaskit/fonts.dart b/lib/web_ui/lib/src/engine/canvaskit/fonts.dart index 908c8aa317921..e984b1deb663f 100644 --- a/lib/web_ui/lib/src/engine/canvaskit/fonts.dart +++ b/lib/web_ui/lib/src/engine/canvaskit/fonts.dart @@ -6,6 +6,7 @@ import 'dart:async'; import 'dart:typed_data'; import 'package:ui/src/engine.dart'; +import 'package:ui/ui_web/src/ui_web.dart' as ui_web; // This URL was found by using the Google Fonts Developer API to find the URL // for Roboto. The API warns that this URL is not stable. In order to update @@ -109,7 +110,7 @@ class SkiaFontCollection implements FlutterFontCollection { loadedRoboto = true; } for (final FontAsset fontAsset in family.fontAssets) { - final String url = assetManager.getAssetUrl(fontAsset.asset); + final String url = ui_web.assetManager.getAssetUrl(fontAsset.asset); pendingDownloads.add(_downloadFont(fontAsset.asset, url, family.name)); } } diff --git a/lib/web_ui/lib/src/engine/canvaskit/renderer.dart b/lib/web_ui/lib/src/engine/canvaskit/renderer.dart index 07fd58edfe841..834446ef26d82 100644 --- a/lib/web_ui/lib/src/engine/canvaskit/renderer.dart +++ b/lib/web_ui/lib/src/engine/canvaskit/renderer.dart @@ -8,6 +8,7 @@ import 'dart:typed_data'; import 'package:ui/src/engine.dart'; import 'package:ui/ui.dart' as ui; +import 'package:ui/ui_web/src/ui_web.dart' as ui_web; enum CanvasKitVariant { /// The appropriate variant is chosen based on the browser. @@ -384,7 +385,7 @@ class CanvasKitRenderer implements Renderer { if (_programs.containsKey(assetKey)) { return _programs[assetKey]!; } - return _programs[assetKey] = assetManager.load(assetKey).then((ByteData data) { + return _programs[assetKey] = ui_web.assetManager.load(assetKey).then((ByteData data) { return CkFragmentProgram.fromBytes(assetKey, data.buffer.asUint8List()); }); } diff --git a/lib/web_ui/lib/src/engine/fonts.dart b/lib/web_ui/lib/src/engine/fonts.dart index 07c4154891f2b..3d51de4fb33a6 100644 --- a/lib/web_ui/lib/src/engine/fonts.dart +++ b/lib/web_ui/lib/src/engine/fonts.dart @@ -8,6 +8,7 @@ import 'dart:js_interop'; import 'dart:typed_data'; import 'package:ui/src/engine.dart'; +import 'package:ui/ui_web/src/ui_web.dart' as ui_web; class FontAsset { FontAsset(this.asset, this.descriptors); @@ -29,8 +30,8 @@ class FontManifest { final List families; } -Future fetchFontManifest(AssetManager assetManager) async { - final HttpFetchResponse response = await assetManager.loadAsset('FontManifest.json'); +Future fetchFontManifest(ui_web.AssetManager assetManager) async { + final HttpFetchResponse response = await assetManager.loadAsset('FontManifest.json') as HttpFetchResponse; if (!response.hasPayload) { printWarning('Font manifest does not exist at `${response.url}` - ignoring.'); return FontManifest([]); diff --git a/lib/web_ui/lib/src/engine/initialization.dart b/lib/web_ui/lib/src/engine/initialization.dart index c4fb28b82b12a..7d265c424c17b 100644 --- a/lib/web_ui/lib/src/engine/initialization.dart +++ b/lib/web_ui/lib/src/engine/initialization.dart @@ -8,6 +8,7 @@ import 'dart:js_interop'; import 'package:ui/src/engine.dart'; import 'package:ui/ui.dart' as ui; +import 'package:ui/ui_web/src/ui_web.dart' as ui_web; import 'package:web_test_fonts/web_test_fonts.dart'; /// The mode the app is running in. @@ -56,7 +57,7 @@ void debugEmulateHotRestart() { /// Fully initializes the engine, including services and UI. Future initializeEngine({ - AssetManager? assetManager, + ui_web.AssetManager? assetManager, }) async { await initializeEngineServices(assetManager: assetManager); await initializeEngineUi(); @@ -114,7 +115,7 @@ void debugResetEngineInitializationState() { /// * [initializeEngineUi], which is typically called after this function, and /// puts UI elements on the page. Future initializeEngineServices({ - AssetManager? assetManager, + ui_web.AssetManager? assetManager, JsFlutterConfiguration? jsConfiguration }) async { if (_initializationState != DebugEngineInitializationState.uninitialized) { @@ -193,7 +194,7 @@ Future initializeEngineServices({ } }; - assetManager ??= AssetManager(assetBase: configuration.assetBase); + assetManager ??= ui_web.AssetManager(assetBase: configuration.assetBase); _setAssetManager(assetManager); Future initializeRendererCallback () async => renderer.initialize(); @@ -229,10 +230,10 @@ Future initializeEngineUi() async { _initializationState = DebugEngineInitializationState.initialized; } -AssetManager get assetManager => _assetManager!; -AssetManager? _assetManager; +ui_web.AssetManager get engineAssetManager => _assetManager!; +ui_web.AssetManager? _assetManager; -void _setAssetManager(AssetManager assetManager) { +void _setAssetManager(ui_web.AssetManager assetManager) { if (assetManager == _assetManager) { return; } @@ -253,7 +254,7 @@ Future _downloadAssetFonts() async { } if (_assetManager != null) { - await renderer.fontCollection.loadAssetFonts(await fetchFontManifest(assetManager)); + await renderer.fontCollection.loadAssetFonts(await fetchFontManifest(ui_web.assetManager)); } } diff --git a/lib/web_ui/lib/src/engine/platform_dispatcher.dart b/lib/web_ui/lib/src/engine/platform_dispatcher.dart index 4e1f641c14114..40b8a0ed4faab 100644 --- a/lib/web_ui/lib/src/engine/platform_dispatcher.dart +++ b/lib/web_ui/lib/src/engine/platform_dispatcher.dart @@ -7,22 +7,10 @@ import 'dart:convert'; import 'dart:js_interop'; import 'dart:typed_data'; -import 'package:ui/src/engine/canvaskit/renderer.dart'; -import 'package:ui/src/engine/renderer.dart'; import 'package:ui/ui.dart' as ui; +import 'package:ui/ui_web/src/ui_web.dart' as ui_web; -import '../engine.dart' show flutterViewEmbedder, platformViewManager, registerHotRestartListener; -import 'clipboard.dart'; -import 'dom.dart'; -import 'mouse_cursor.dart'; -import 'platform_views/message_handler.dart'; -import 'plugins.dart'; -import 'safe_browser_api.dart'; -import 'semantics.dart'; -import 'services.dart'; -import 'text_editing/text_editing.dart'; -import 'util.dart'; -import 'window.dart'; +import '../engine.dart'; /// Requests that the browser schedule a frame. /// @@ -688,7 +676,7 @@ class EnginePlatformDispatcher extends ui.PlatformDispatcher { Future _handleFlutterAssetsMessage(String url, ui.PlatformMessageResponseCallback? callback) async { try { - final HttpFetchResponse response = await ui.webOnlyAssetManager.loadAsset(url); + final HttpFetchResponse response = await ui_web.assetManager.loadAsset(url) as HttpFetchResponse; final ByteBuffer assetData = await response.asByteBuffer(); replyToPlatformMessage(callback, assetData.asByteData()); } catch (error) { diff --git a/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/font_collection.dart b/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/font_collection.dart index e71b5eb785d33..f5c544bbd827f 100644 --- a/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/font_collection.dart +++ b/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/font_collection.dart @@ -10,6 +10,7 @@ import 'dart:typed_data'; import 'package:ui/src/engine.dart'; import 'package:ui/src/engine/skwasm/skwasm_impl.dart'; +import 'package:ui/ui_web/src/ui_web.dart' as ui_web; // This URL was found by using the Google Fonts Developer API to find the URL // for Roboto. The API warns that this URL is not stable. In order to update @@ -99,12 +100,12 @@ class SkwasmFontCollection implements FlutterFontCollection { Future _downloadFontAsset(FontAsset asset, String family) async { final HttpFetchResponse response; try { - response = await assetManager.loadAsset(asset.asset); + response = await ui_web.assetManager.loadAsset(asset.asset) as HttpFetchResponse; } catch (error) { - return FontDownloadError(assetManager.getAssetUrl(asset.asset), error); + return FontDownloadError(ui_web.assetManager.getAssetUrl(asset.asset), error); } if (!response.hasPayload) { - return FontNotFoundError(assetManager.getAssetUrl(asset.asset)); + return FontNotFoundError(ui_web.assetManager.getAssetUrl(asset.asset)); } int length = 0; final List chunks = []; @@ -128,7 +129,7 @@ class SkwasmFontCollection implements FlutterFontCollection { skStringFree(familyNameHandle); return null; } else { - return FontInvalidDataError(assetManager.getAssetUrl(asset.asset)); + return FontInvalidDataError(ui_web.assetManager.getAssetUrl(asset.asset)); } } diff --git a/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/renderer.dart b/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/renderer.dart index 46ec0fe541477..e8228815ac806 100644 --- a/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/renderer.dart +++ b/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/renderer.dart @@ -10,6 +10,7 @@ import 'dart:typed_data'; import 'package:ui/src/engine.dart'; import 'package:ui/src/engine/skwasm/skwasm_impl.dart'; import 'package:ui/ui.dart' as ui; +import 'package:ui/ui_web/src/ui_web.dart' as ui_web; class SkwasmRenderer implements Renderer { late DomCanvasElement sceneElement; @@ -438,7 +439,7 @@ class SkwasmRenderer implements Renderer { if (_programs.containsKey(assetKey)) { return _programs[assetKey]!; } - return _programs[assetKey] = assetManager.load(assetKey).then((ByteData data) { + return _programs[assetKey] = ui_web.assetManager.load(assetKey).then((ByteData data) { return SkwasmFragmentProgram.fromBytes(assetKey, data.buffer.asUint8List()); }); } diff --git a/lib/web_ui/lib/src/engine/skwasm/skwasm_stub/renderer.dart b/lib/web_ui/lib/src/engine/skwasm/skwasm_stub/renderer.dart index 524de360fb16f..3d4823f49cc2c 100644 --- a/lib/web_ui/lib/src/engine/skwasm/skwasm_stub/renderer.dart +++ b/lib/web_ui/lib/src/engine/skwasm/skwasm_stub/renderer.dart @@ -8,6 +8,7 @@ import 'dart:typed_data'; import 'package:ui/src/engine.dart'; import 'package:ui/ui.dart' as ui; +import 'package:ui/ui_web/src/ui_web.dart' as ui_web; class SkwasmRenderer implements Renderer { @override @@ -171,7 +172,7 @@ class SkwasmRenderer implements Renderer { if (_programs.containsKey(assetKey)) { return _programs[assetKey]!; } - return _programs[assetKey] = assetManager.load(assetKey).then((ByteData data) { + return _programs[assetKey] = ui_web.assetManager.load(assetKey).then((ByteData data) { return CkFragmentProgram.fromBytes(assetKey, data.buffer.asUint8List()); }); } diff --git a/lib/web_ui/lib/src/engine/text/font_collection.dart b/lib/web_ui/lib/src/engine/text/font_collection.dart index cef9a9e02306d..fca0270597468 100644 --- a/lib/web_ui/lib/src/engine/text/font_collection.dart +++ b/lib/web_ui/lib/src/engine/text/font_collection.dart @@ -6,6 +6,7 @@ import 'dart:async'; import 'dart:typed_data'; import 'package:ui/src/engine.dart'; +import 'package:ui/ui_web/src/ui_web.dart' as ui_web; /// This class is responsible for registering and loading fonts. /// @@ -14,7 +15,7 @@ import 'package:ui/src/engine.dart'; /// font manifest. If test fonts are enabled, then call /// [debugDownloadTestFonts] as well. class HtmlFontCollection implements FlutterFontCollection { - /// Reads the font manifest using the [assetManager] and downloads all of the + /// Reads the font manifest using the [ui_web.assetManager] and downloads all of the /// fonts declared within. @override Future loadAssetFonts(FontManifest manifest) async { @@ -149,7 +150,7 @@ class HtmlFontCollection implements FlutterFontCollection { ) async { // try/catch because `new FontFace` can crash with an improper font family. try { - final DomFontFace fontFace = createDomFontFace(family, 'url(${assetManager.getAssetUrl(asset)})', descriptors); + final DomFontFace fontFace = createDomFontFace(family, 'url(${ui_web.assetManager.getAssetUrl(asset)})', descriptors); return await fontFace.load(); } catch (e) { printWarning('Error while loading font family "$family":\n$e'); diff --git a/lib/web_ui/lib/ui_web/src/ui_web.dart b/lib/web_ui/lib/ui_web/src/ui_web.dart index d5731cc73b1f7..7327584344738 100644 --- a/lib/web_ui/lib/ui_web/src/ui_web.dart +++ b/lib/web_ui/lib/ui_web/src/ui_web.dart @@ -8,6 +8,7 @@ // ignore: unnecessary_library_directive library ui_web; +export 'ui_web/asset_manager.dart'; export 'ui_web/navigation/platform_location.dart'; export 'ui_web/navigation/url_strategy.dart'; export 'ui_web/platform_view_registry.dart'; diff --git a/lib/web_ui/lib/src/engine/assets.dart b/lib/web_ui/lib/ui_web/src/ui_web/asset_manager.dart similarity index 93% rename from lib/web_ui/lib/src/engine/assets.dart rename to lib/web_ui/lib/ui_web/src/ui_web/asset_manager.dart index 585f9d4f39dad..de8574c94e936 100644 --- a/lib/web_ui/lib/src/engine/assets.dart +++ b/lib/web_ui/lib/ui_web/src/ui_web/asset_manager.dart @@ -5,8 +5,10 @@ import 'dart:convert'; import 'dart:typed_data'; -import 'dom.dart'; -import 'util.dart'; +import 'package:ui/src/engine.dart'; + +/// Provides the [AssetManager] used by the Flutter Engine. +AssetManager get assetManager => engineAssetManager; /// This class downloads assets over the network. /// @@ -79,11 +81,11 @@ class AssetManager { } /// Loads an asset and returns the server response. - Future loadAsset(String asset) { + Future loadAsset(String asset) { return httpFetch(getAssetUrl(asset)); } - /// Loads an asset using an [DomXMLHttpRequest] and returns data as [ByteData]. + /// Loads an asset using an [XMLHttpRequest] and returns data as [ByteData]. Future load(String asset) async { final String url = getAssetUrl(asset); final HttpFetchResponse response = await httpFetch(url); diff --git a/lib/web_ui/test/common/fake_asset_manager.dart b/lib/web_ui/test/common/fake_asset_manager.dart index 8b62c1ead6854..a1099fb58aaff 100644 --- a/lib/web_ui/test/common/fake_asset_manager.dart +++ b/lib/web_ui/test/common/fake_asset_manager.dart @@ -6,8 +6,9 @@ import 'dart:convert'; import 'dart:typed_data'; import 'package:ui/src/engine.dart'; +import 'package:ui/ui_web/src/ui_web.dart' as ui_web; -class FakeAssetManager implements AssetManager { +class FakeAssetManager implements ui_web.AssetManager { FakeAssetManager(); @override diff --git a/lib/web_ui/test/engine/assets_test.dart b/lib/web_ui/test/engine/assets_test.dart index c4602f24345c1..bb1b0080b4aec 100644 --- a/lib/web_ui/test/engine/assets_test.dart +++ b/lib/web_ui/test/engine/assets_test.dart @@ -8,6 +8,7 @@ library; import 'package:test/bootstrap/browser.dart'; import 'package:test/test.dart'; import 'package:ui/src/engine.dart'; +import 'package:ui/ui_web/src/ui_web.dart' as ui_web; import '../common/matchers.dart'; @@ -23,7 +24,7 @@ void testMain() { }); test('initializes with default values', () { - final AssetManager assets = AssetManager(); + final ui_web.AssetManager assets = ui_web.AssetManager(); expect( assets.getAssetUrl('asset.txt'), @@ -33,25 +34,25 @@ void testMain() { }); test('assetsDir changes the directory where assets are stored', () { - final AssetManager assets = AssetManager(assetsDir: 'static'); + final ui_web.AssetManager assets = ui_web.AssetManager(assetsDir: 'static'); expect(assets.getAssetUrl('asset.txt'), 'static/asset.txt'); }); test('assetBase must end with slash', () { expect(() { - AssetManager(assetBase: '/deployment'); + ui_web.AssetManager(assetBase: '/deployment'); }, throwsAssertionError); }); test('assetBase can be relative', () { - final AssetManager assets = AssetManager(assetBase: 'base/'); + final ui_web.AssetManager assets = ui_web.AssetManager(assetBase: 'base/'); expect(assets.getAssetUrl('asset.txt'), 'base/assets/asset.txt'); }); test('assetBase can be absolute', () { - final AssetManager assets = AssetManager( + final ui_web.AssetManager assets = ui_web.AssetManager( assetBase: 'https://www.gstatic.com/my-app/', ); @@ -62,7 +63,7 @@ void testMain() { }); test('assetBase in conjunction with assetsDir, fully custom paths', () { - final AssetManager assets = AssetManager( + final ui_web.AssetManager assets = ui_web.AssetManager( assetBase: '/asset/base/', assetsDir: 'static', ); @@ -71,7 +72,7 @@ void testMain() { }); test('Fully-qualified asset URLs are untouched', () { - final AssetManager assets = AssetManager(); + final ui_web.AssetManager assets = ui_web.AssetManager(); expect( assets.getAssetUrl('https://static.my-app.com/favicon.ico'), @@ -80,7 +81,7 @@ void testMain() { }); test('Fully-qualified asset URLs are untouched (even with assetBase)', () { - final AssetManager assets = AssetManager( + final ui_web.AssetManager assets = ui_web.AssetManager( assetBase: 'https://static.my-app.com/', ); @@ -98,20 +99,20 @@ void testMain() { }); test('reads value from DOM', () { - final AssetManager assets = AssetManager(); + final ui_web.AssetManager assets = ui_web.AssetManager(); expect(assets.getAssetUrl('asset.txt'), '/dom/base/assets/asset.txt'); }); test('reads value from DOM (only once!)', () { - final AssetManager firstManager = AssetManager(); + final ui_web.AssetManager firstManager = ui_web.AssetManager(); expect( firstManager.getAssetUrl('asset.txt'), '/dom/base/assets/asset.txt', ); removeAssetBaseMeta(); - final AssetManager anotherManager = AssetManager(); + final ui_web.AssetManager anotherManager = ui_web.AssetManager(); expect( firstManager.getAssetUrl('asset.txt'),